-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat($Common): add new module
Auth Center
Add new module `Auth Center`: Authentication and Authorization Center (AAC) for incoming requests from clients. BREAKING CHANGE: support Redis operations
- Loading branch information
1 parent
ce67791
commit 720475b
Showing
55 changed files
with
2,672 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Getting Started | ||
|
||
### Reference Documentation | ||
For further reference, please consider the following sections: | ||
|
||
* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html) | ||
* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/maven-plugin/) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<!-- Sub-module Basics --> | ||
<artifactId>auth-center</artifactId> | ||
<name>Auth Center</name> | ||
<description>Authentication and Authorization Center (AAC) for incoming requests from clients.</description> | ||
<properties> | ||
<java.version>11</java.version> | ||
<port>8770</port> | ||
</properties> | ||
<parent> | ||
<groupId>com.jmsoftware</groupId> | ||
<artifactId>muscle-and-fitness-server</artifactId> | ||
<version>0.0.1-SNAPSHOT</version> | ||
</parent> | ||
|
||
<!-- Build Settings --> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-maven-plugin</artifactId> | ||
</plugin> | ||
|
||
<!-- https://github.com/GoogleContainerTools/jib/blob/master/jib-maven-plugin/README.md --> | ||
<plugin> | ||
<groupId>com.google.cloud.tools</groupId> | ||
<artifactId>jib-maven-plugin</artifactId> | ||
<version>2.0.0</version> | ||
<executions> | ||
<!-- Bind `jib:dockerBuild` to a Maven lifecycle `compile`. | ||
Jib will build your image directly to a Docker daemon. --> | ||
<execution> | ||
<id>compilingPhaseJib</id> | ||
<phase>compile</phase> | ||
<goals> | ||
<goal>dockerBuild</goal> | ||
</goals> | ||
</execution> | ||
<!-- Bind `jib:build` to a Maven lifecycle `package`. | ||
Jib will build and push image to image registry. --> | ||
<execution> | ||
<id>packagingPhaseJib</id> | ||
<phase>package</phase> | ||
<goals> | ||
<goal>build</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
<configuration> | ||
<from> | ||
<image>openjdk:11.0.5-slim</image> | ||
</from> | ||
<to> | ||
<image>docker.io/ijohnnymiller/${project.artifactId}-${envAlias}</image> | ||
<tags> | ||
<tag>${project.version}</tag> | ||
</tags> | ||
</to> | ||
<container> | ||
<!-- The root directory on the container where the app's contents are placed. --> | ||
<appRoot>/${project.artifactId}-${envAlias}</appRoot> | ||
<jvmFlags> | ||
<jvmFlag>-Xmx256m</jvmFlag> | ||
</jvmFlags> | ||
<ports> | ||
<port>${port}</port> | ||
</ports> | ||
<creationTime>USE_CURRENT_TIMESTAMP</creationTime> | ||
</container> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
<!-- Scoped Dependencies Management --> | ||
<dependencies> | ||
<!-- Spring Frameworks --> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-web</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.cloud</groupId> | ||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>de.codecentric</groupId> | ||
<artifactId>spring-boot-admin-starter-client</artifactId> | ||
<version>${spring-boot-admin.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.cloud</groupId> | ||
<artifactId>spring-cloud-starter-zipkin</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-data-redis</artifactId> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>com.jmsoftware</groupId> | ||
<artifactId>common</artifactId> | ||
<version>0.0.1-SNAPSHOT</version> | ||
</dependency> | ||
|
||
<!-- ORM Library --> | ||
<dependency> | ||
<groupId>com.baomidou</groupId> | ||
<artifactId>mybatis-plus-boot-starter</artifactId> | ||
<version>3.3.1</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>mysql</groupId> | ||
<artifactId>mysql-connector-java</artifactId> | ||
<scope>runtime</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.alibaba</groupId> | ||
<artifactId>druid</artifactId> | ||
<version>1.1.21</version> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>redis.clients</groupId> | ||
<artifactId>jedis</artifactId> | ||
</dependency> | ||
</dependencies> | ||
</project> |
51 changes: 51 additions & 0 deletions
51
auth-center/src/main/java/com/jmsoftware/authcenter/AuthCenterApplication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package com.jmsoftware.authcenter; | ||
|
||
import com.jmsoftware.authcenter.universal.configuration.ProjectProperty; | ||
import com.jmsoftware.authcenter.universal.configuration.ServerConfiguration; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.boot.SpringApplication; | ||
import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; | ||
import org.springframework.cloud.openfeign.EnableFeignClients; | ||
|
||
import java.time.Duration; | ||
import java.time.Instant; | ||
import java.util.TimeZone; | ||
|
||
/** | ||
* <h1>AuthCenterApplication</h1> | ||
* <p> | ||
* Change description here. | ||
* | ||
* @author Johnny Miller (鍾俊), email: johnnysviva@outlook.com | ||
* @date 3/12/20 9:57 AM | ||
**/ | ||
@Slf4j | ||
@EnableFeignClients | ||
@EnableDiscoveryClient | ||
@SpringBootApplication | ||
public class AuthCenterApplication { | ||
private static final String LINE_SEPARATOR = System.lineSeparator(); | ||
private static ProjectProperty projectProperty; | ||
private static ServerConfiguration serverConfiguration; | ||
|
||
public AuthCenterApplication(ProjectProperty projectProperty, ServerConfiguration serverConfiguration) { | ||
AuthCenterApplication.projectProperty = projectProperty; | ||
AuthCenterApplication.serverConfiguration = serverConfiguration; | ||
} | ||
|
||
public static void main(String[] args) { | ||
var startInstant = Instant.now(); | ||
SpringApplication.run(AuthCenterApplication.class, args); | ||
var endInstant = Instant.now(); | ||
var duration = Duration.between(startInstant, endInstant); | ||
log.info("🥳 Congratulations! 🎉"); | ||
log.info("🖥 {}@{} started!", projectProperty.getProjectArtifactId(), projectProperty.getVersion()); | ||
log.info("⚙️ Environment: {} ({})", projectProperty.getEnvironment(), projectProperty.getEnvironmentAlias()); | ||
log.info("⏳ Deployment duration: {} seconds ({} ms)", duration.getSeconds(), duration.toMillis()); | ||
log.info("⏰ App started at {} (timezone - {})", endInstant, TimeZone.getDefault().getDisplayName()); | ||
log.info("{} App running at{} - Local: http://localhost:{}{}/{} - Network: {}/", | ||
LINE_SEPARATOR, LINE_SEPARATOR, serverConfiguration.getServerPort(), projectProperty.getContextPath(), | ||
LINE_SEPARATOR, serverConfiguration.getBaseUrl()); | ||
} | ||
} |
138 changes: 138 additions & 0 deletions
138
...r/src/main/java/com/jmsoftware/authcenter/universal/aspect/ExceptionControllerAdvice.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
package com.jmsoftware.authcenter.universal.aspect; | ||
|
||
import cn.hutool.core.collection.CollUtil; | ||
import cn.hutool.json.JSONUtil; | ||
import com.jmsoftware.common.bean.ResponseBodyBean; | ||
import com.jmsoftware.common.constant.HttpStatus; | ||
import com.jmsoftware.common.exception.BaseException; | ||
import com.jmsoftware.common.util.RequestUtil; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.context.support.DefaultMessageSourceResolvable; | ||
import org.springframework.http.converter.HttpMessageNotReadableException; | ||
import org.springframework.validation.BindException; | ||
import org.springframework.web.HttpRequestMethodNotSupportedException; | ||
import org.springframework.web.bind.MethodArgumentNotValidException; | ||
import org.springframework.web.bind.annotation.ControllerAdvice; | ||
import org.springframework.web.bind.annotation.ExceptionHandler; | ||
import org.springframework.web.bind.annotation.ResponseBody; | ||
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; | ||
import org.springframework.web.servlet.NoHandlerFoundException; | ||
|
||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import javax.validation.ConstraintViolationException; | ||
import java.util.Objects; | ||
|
||
/** | ||
* <h1>ExceptionControllerAdvice</h1> | ||
* <p> | ||
* Exception advice for global controllers. | ||
* | ||
* @author Johnny Miller (鍾俊), email: johnnysviva@outlook.com | ||
* @date 2019-03-02 17:39 | ||
**/ | ||
@Slf4j | ||
@ControllerAdvice | ||
public class ExceptionControllerAdvice { | ||
/** | ||
* <p>Exception handler.</p> | ||
* <p><strong>ATTENTION</strong>: In this method, <strong><em>cannot throw any exception</em></strong>.</p> | ||
* | ||
* @param request HTTP request | ||
* @param exception any kinds of exception occurred in controller | ||
* @return custom exception info | ||
*/ | ||
@ResponseBody | ||
@ExceptionHandler(value = Exception.class) | ||
public ResponseBodyBean<Object> handleException(HttpServletRequest request, | ||
HttpServletResponse response, | ||
Exception exception) { | ||
log.error("Exception occurred when [{}] requested access. URL: {}", | ||
RequestUtil.getRequestIpAndPort(request), | ||
request.getServletPath()); | ||
|
||
// FIXME: THIS IS NOT A PROBLEM | ||
// ATTENTION: Use only ResponseBodyBean.ofStatus() in handleException() method and DON'T throw any exception | ||
if (exception instanceof NoHandlerFoundException) { | ||
log.error("[GlobalExceptionCapture] NoHandlerFoundException: Request URL = {}, HTTP method = {}", | ||
((NoHandlerFoundException) exception).getRequestURL(), | ||
((NoHandlerFoundException) exception).getHttpMethod()); | ||
response.setStatus(HttpStatus.NOT_FOUND.getCode()); | ||
return ResponseBodyBean.ofStatus(HttpStatus.NOT_FOUND); | ||
} else if (exception instanceof HttpRequestMethodNotSupportedException) { | ||
log.error("[GlobalExceptionCapture] HttpRequestMethodNotSupportedException: " + | ||
"Current method is {}, Support HTTP method = {}", | ||
((HttpRequestMethodNotSupportedException) exception).getMethod(), | ||
JSONUtil.toJsonStr( | ||
((HttpRequestMethodNotSupportedException) exception).getSupportedHttpMethods())); | ||
response.setStatus(HttpStatus.METHOD_NOT_ALLOWED.getCode()); | ||
return ResponseBodyBean.ofStatus(HttpStatus.METHOD_NOT_ALLOWED); | ||
} else if (exception instanceof MethodArgumentNotValidException) { | ||
log.error("[GlobalExceptionCapture] MethodArgumentNotValidException: {}", exception.getMessage()); | ||
response.setStatus(HttpStatus.BAD_REQUEST.getCode()); | ||
return ResponseBodyBean.ofStatus(HttpStatus.BAD_REQUEST.getCode(), | ||
getFieldErrorMessageFromException((MethodArgumentNotValidException) exception), | ||
null); | ||
} else if (exception instanceof ConstraintViolationException) { | ||
log.error("[GlobalExceptionCapture] ConstraintViolationException: {}", exception.getMessage()); | ||
response.setStatus(HttpStatus.BAD_REQUEST.getCode()); | ||
return ResponseBodyBean.ofStatus(HttpStatus.BAD_REQUEST.getCode(), | ||
CollUtil.getFirst(((ConstraintViolationException) exception) | ||
.getConstraintViolations()) | ||
.getMessage(), null); | ||
} else if (exception instanceof MethodArgumentTypeMismatchException) { | ||
log.error("[GlobalExceptionCapture] MethodArgumentTypeMismatchException: " + | ||
"Parameter name = {}, Exception information: {}", | ||
((MethodArgumentTypeMismatchException) exception).getName(), | ||
((MethodArgumentTypeMismatchException) exception).getMessage()); | ||
response.setStatus(HttpStatus.PARAM_NOT_MATCH.getCode()); | ||
return ResponseBodyBean.ofStatus(HttpStatus.PARAM_NOT_MATCH); | ||
} else if (exception instanceof HttpMessageNotReadableException) { | ||
log.error("[GlobalExceptionCapture] HttpMessageNotReadableException: {}", | ||
((HttpMessageNotReadableException) exception).getMessage()); | ||
response.setStatus(HttpStatus.PARAM_NOT_NULL.getCode()); | ||
return ResponseBodyBean.ofStatus(HttpStatus.PARAM_NOT_NULL); | ||
} else if (exception instanceof BaseException) { | ||
log.error("[GlobalExceptionCapture] BaseException: Status code: {}, message: {}, data: {}", | ||
((BaseException) exception).getCode(), | ||
exception.getMessage(), | ||
((BaseException) exception).getData()); | ||
response.setStatus(((BaseException) exception).getCode()); | ||
return ResponseBodyBean.ofStatus(((BaseException) exception).getCode(), | ||
exception.getMessage(), | ||
((BaseException) exception).getData()); | ||
} else if (exception instanceof BindException) { | ||
log.error("[GlobalExceptionCapture]: Exception information: {} ", exception.getMessage()); | ||
response.setStatus(HttpStatus.INVALID_PARAM.getCode()); | ||
return ResponseBodyBean.ofStatus(HttpStatus.INVALID_PARAM); | ||
} | ||
log.error("[GlobalExceptionCapture]: Exception information: {} ", exception.getMessage(), exception); | ||
response.setStatus(HttpStatus.ERROR.getCode()); | ||
return ResponseBodyBean.ofStatus(HttpStatus.ERROR.getCode(), HttpStatus.ERROR.getMessage(), null); | ||
} | ||
|
||
/** | ||
* Get field error message from exception. If two or more fields do not pass Spring Validation check, then will | ||
* return the 1st error message of the error field. | ||
* | ||
* @param exception MethodArgumentNotValidException | ||
* @return field error message | ||
*/ | ||
private String getFieldErrorMessageFromException(MethodArgumentNotValidException exception) { | ||
try { | ||
DefaultMessageSourceResolvable firstErrorField = | ||
(DefaultMessageSourceResolvable) Objects.requireNonNull(exception.getBindingResult() | ||
.getAllErrors() | ||
.get(0) | ||
.getArguments())[0]; | ||
String firstErrorFieldName = firstErrorField.getDefaultMessage(); | ||
String firstErrorFieldMessage = exception.getBindingResult().getAllErrors().get(0).getDefaultMessage(); | ||
return firstErrorFieldName + " " + firstErrorFieldMessage; | ||
} catch (Exception e) { | ||
log.error("Exception occurred when get field error message from exception. Exception message: {}", | ||
e.getMessage(), | ||
e); | ||
return HttpStatus.INVALID_PARAM.getMessage(); | ||
} | ||
} | ||
} |
Oops, something went wrong.