Skip to content

Commit e1e8838

Browse files
committed
代码同步
1 parent 6bd1255 commit e1e8838

File tree

8 files changed

+302
-2
lines changed

8 files changed

+302
-2
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
## 2.2.2.RELEASE更新日志(2020-1-6日发布)
2+
- 支持自定义认证服务器OAuth2认证失败时响应内容,详见:[I17O6B](https://gitee.com/minbox-projects/api-boot/issues/I17O6B)
3+
- 回退fastJson版本为1.2.60
4+
- 升级分布式链路日志minbox-logging为1.0.3.RELEASE
5+
- 提供自定义认证失败使用示例,[CustomAuthorizationDeniedResponse](https://gitee.com/minbox-projects/api-boot/blob/master/api-boot-samples/api-boot-sample-security-oauth-jwt/src/main/java/org/minbox/framework/api/boot/sample/CustomAuthorizationDeniedResponse.java)
6+
- 提供默认`AuthorizationDeniedResponse`默认实现[DefaultAuthorizationDeniedResponse](https://gitee.com/minbox-projects/api-boot/blob/master/api-boot-project/api-boot-plugins/api-boot-plugin-oauth/src/main/java/org/minbox/framework/api/boot/plugin/oauth/response/DefaultAuthorizationDeniedResponse.java)
7+
- 修复minbox-logging采集日志发生位置错误问题
8+
- 统一部分源码类上的注释格式
9+
- ApiBoot提供`WebResponseExceptionTranslator`实现类[ApiBootWebResponseExceptionTranslator](https://gitee.com/minbox-projects/api-boot/blob/master/api-boot-project/api-boot-plugins/api-boot-plugin-oauth/src/main/java/org/minbox/framework/api/boot/plugin/oauth/translator/ApiBootWebResponseExceptionTranslator.java) ,用于处理OAuth2Exception异常。
10+
111
## 2.2.1.RELEASE更新日志(2019-12-16日发布)
212
- 升级SpringBoot版本为2.2.2.RELEASE
313
- 升级minbox-logging版本为1.0.3.RC1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.minbox.framework.api.boot.plugin.oauth.exception;
2+
3+
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
4+
import lombok.Getter;
5+
import org.minbox.framework.api.boot.plugin.oauth.response.AuthorizationDeniedResponse;
6+
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
7+
8+
/**
9+
* Custom implementation of OAuth2Exception
10+
*
11+
* @author 恒宇少年
12+
* @see OAuth2Exception
13+
*/
14+
@JsonSerialize(using = ApiBootOAuth2ExceptionSerializer.class)
15+
@Getter
16+
public class ApiBootOAuth2Exception extends OAuth2Exception {
17+
18+
private AuthorizationDeniedResponse response;
19+
20+
public ApiBootOAuth2Exception(String message, Throwable t, AuthorizationDeniedResponse response) {
21+
super(message, t);
22+
this.response = response;
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.minbox.framework.api.boot.plugin.oauth.exception;
2+
3+
import com.fasterxml.jackson.core.JsonGenerator;
4+
import com.fasterxml.jackson.databind.SerializerProvider;
5+
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
6+
7+
import java.io.IOException;
8+
9+
/**
10+
* The ApiBootOAuth2Exception Serializer
11+
* The specific implementation is handed over to "org.minbox.framework.api.boot.plugin.oauth.response.AuthorizationDeniedResponse#serializeResponse"
12+
*
13+
* @author 恒宇少年
14+
*/
15+
public class ApiBootOAuth2ExceptionSerializer extends StdSerializer<ApiBootOAuth2Exception> {
16+
protected ApiBootOAuth2ExceptionSerializer() {
17+
super(ApiBootOAuth2Exception.class);
18+
}
19+
20+
@Override
21+
public void serialize(ApiBootOAuth2Exception e, JsonGenerator generator, SerializerProvider serializerProvider) throws IOException {
22+
generator.writeStartObject();
23+
e.getResponse().serializeResponse(e, generator);
24+
generator.writeEndObject();
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package org.minbox.framework.api.boot.plugin.oauth.response;
2+
3+
import com.fasterxml.jackson.core.JsonGenerator;
4+
import org.minbox.framework.api.boot.plugin.oauth.exception.ApiBootOAuth2Exception;
5+
import org.springframework.http.HttpStatus;
6+
7+
import java.io.Serializable;
8+
9+
/**
10+
* Interface definition to respond to authorization exception
11+
*
12+
* @author 恒宇少年
13+
*/
14+
public interface AuthorizationDeniedResponse {
15+
/**
16+
* Provide the response HttpStatus, default is 401
17+
*
18+
* @return {@link HttpStatus}
19+
*/
20+
default HttpStatus getHttpStatus() {
21+
return HttpStatus.UNAUTHORIZED;
22+
}
23+
24+
/**
25+
* Serialize the response content
26+
*
27+
* @param e {@link ApiBootOAuth2Exception}
28+
* @param generator {@link JsonGenerator}
29+
*/
30+
default void serializeResponse(ApiBootOAuth2Exception e, JsonGenerator generator) {
31+
// default nothing to do
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package org.minbox.framework.api.boot.plugin.oauth.response;
2+
3+
import com.fasterxml.jackson.core.JsonGenerator;
4+
import org.minbox.framework.api.boot.plugin.oauth.exception.ApiBootOAuth2Exception;
5+
import org.springframework.http.HttpStatus;
6+
import org.springframework.web.util.HtmlUtils;
7+
8+
/**
9+
* The default {@link AuthorizationDeniedResponse} support
10+
* Provide default OAuth2Exception exception response content
11+
*
12+
* @author 恒宇少年
13+
* @see org.minbox.framework.api.boot.plugin.oauth.translator.ApiBootWebResponseExceptionTranslator
14+
* @see ApiBootOAuth2Exception
15+
*/
16+
public class DefaultAuthorizationDeniedResponse implements AuthorizationDeniedResponse {
17+
@Override
18+
public void serializeResponse(ApiBootOAuth2Exception e, JsonGenerator generator) {
19+
try {
20+
String message = e.getMessage();
21+
if (message != null) {
22+
message = HtmlUtils.htmlEscape(message);
23+
}
24+
generator.writeObjectField("errorMessage", message);
25+
generator.writeObjectField("errorCode", HttpStatus.UNAUTHORIZED.getReasonPhrase());
26+
} catch (Exception ex) {
27+
ex.printStackTrace();
28+
}
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package org.minbox.framework.api.boot.plugin.oauth.translator;
2+
3+
import org.minbox.framework.api.boot.plugin.oauth.exception.ApiBootOAuth2Exception;
4+
import org.minbox.framework.api.boot.plugin.oauth.response.AuthorizationDeniedResponse;
5+
import org.springframework.http.HttpHeaders;
6+
import org.springframework.http.HttpStatus;
7+
import org.springframework.http.ResponseEntity;
8+
import org.springframework.security.access.AccessDeniedException;
9+
import org.springframework.security.core.AuthenticationException;
10+
import org.springframework.security.oauth2.common.DefaultThrowableAnalyzer;
11+
import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException;
12+
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
13+
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
14+
import org.springframework.security.web.util.ThrowableAnalyzer;
15+
import org.springframework.web.HttpRequestMethodNotSupportedException;
16+
17+
import java.io.IOException;
18+
19+
/**
20+
* Override the default WebResponseExceptionTranslator
21+
* Customize the error message format returned by the authentication server
22+
*
23+
* @author 恒宇少年
24+
* @see org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator
25+
*/
26+
public class ApiBootWebResponseExceptionTranslator implements WebResponseExceptionTranslator {
27+
/**
28+
* Response in case of authentication error
29+
*/
30+
private AuthorizationDeniedResponse authorizationDeniedResponse;
31+
32+
public ApiBootWebResponseExceptionTranslator(AuthorizationDeniedResponse authorizationDeniedResponse) {
33+
this.authorizationDeniedResponse = authorizationDeniedResponse;
34+
}
35+
36+
private ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer();
37+
38+
@Override
39+
public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {
40+
Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(e);
41+
42+
Exception ase = (OAuth2Exception) this.throwableAnalyzer.getFirstThrowableOfType(OAuth2Exception.class, causeChain);
43+
if (ase != null) {
44+
return this.handleOAuth2Exception((OAuth2Exception) ase);
45+
}
46+
47+
ase = (AuthenticationException) this.throwableAnalyzer.getFirstThrowableOfType(AuthenticationException.class, causeChain);
48+
if (ase != null) {
49+
return this.handleOAuth2Exception(new UnauthorizedException(e.getMessage(), e));
50+
}
51+
52+
ase = (AccessDeniedException) this.throwableAnalyzer.getFirstThrowableOfType(AccessDeniedException.class, causeChain);
53+
if (ase instanceof AccessDeniedException) {
54+
return this.handleOAuth2Exception(new ForbiddenException(ase.getMessage(), ase));
55+
}
56+
57+
ase = (HttpRequestMethodNotSupportedException) throwableAnalyzer.getFirstThrowableOfType(
58+
HttpRequestMethodNotSupportedException.class, causeChain);
59+
if (ase instanceof HttpRequestMethodNotSupportedException) {
60+
return handleOAuth2Exception(new MethodNotAllowed(ase.getMessage(), ase));
61+
}
62+
63+
return this.handleOAuth2Exception(new ServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(), e));
64+
}
65+
66+
/**
67+
* Handling Formatted OAuth2Exception Response
68+
*
69+
* @param e {@link OAuth2Exception}
70+
* @return {@link ResponseEntity}
71+
* @throws IOException
72+
*/
73+
private ResponseEntity<OAuth2Exception> handleOAuth2Exception(OAuth2Exception e) throws IOException {
74+
int status = e.getHttpErrorCode();
75+
HttpHeaders headers = new HttpHeaders();
76+
headers.set("Cache-Control", "no-store");
77+
headers.set("Pragma", "no-cache");
78+
if (status == HttpStatus.UNAUTHORIZED.value() || e instanceof InsufficientScopeException) {
79+
headers.set("WWW-Authenticate", String.format("%s %s", "Bearer", e.getSummary()));
80+
}
81+
82+
// use ApiBootOAuth2Exception as the returned exception type
83+
ApiBootOAuth2Exception apiBootOAuth2Exception = new ApiBootOAuth2Exception(e.getMessage(), e, authorizationDeniedResponse);
84+
// get custom authorization definition response HttpStatus
85+
HttpStatus httpStatus = authorizationDeniedResponse.getHttpStatus();
86+
ResponseEntity<OAuth2Exception> response = new ResponseEntity(apiBootOAuth2Exception, headers, httpStatus);
87+
return response;
88+
}
89+
90+
private static class MethodNotAllowed extends OAuth2Exception {
91+
public MethodNotAllowed(String msg, Throwable t) {
92+
super(msg, t);
93+
}
94+
95+
@Override
96+
public String getOAuth2ErrorCode() {
97+
return HttpStatus.METHOD_NOT_ALLOWED.getReasonPhrase();
98+
}
99+
100+
@Override
101+
public int getHttpErrorCode() {
102+
return HttpStatus.METHOD_NOT_ALLOWED.value();
103+
}
104+
}
105+
106+
private static class UnauthorizedException extends OAuth2Exception {
107+
public UnauthorizedException(String msg, Throwable t) {
108+
super(msg, t);
109+
}
110+
111+
@Override
112+
public String getOAuth2ErrorCode() {
113+
return HttpStatus.UNAUTHORIZED.getReasonPhrase();
114+
}
115+
116+
@Override
117+
public int getHttpErrorCode() {
118+
return HttpStatus.UNAUTHORIZED.value();
119+
}
120+
}
121+
122+
private static class ServerErrorException extends OAuth2Exception {
123+
public ServerErrorException(String msg, Throwable t) {
124+
super(msg, t);
125+
}
126+
127+
@Override
128+
public String getOAuth2ErrorCode() {
129+
return HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase();
130+
}
131+
132+
@Override
133+
public int getHttpErrorCode() {
134+
return HttpStatus.INTERNAL_SERVER_ERROR.value();
135+
}
136+
}
137+
138+
private static class ForbiddenException extends OAuth2Exception {
139+
public ForbiddenException(String msg, Throwable t) {
140+
super(msg, t);
141+
}
142+
143+
@Override
144+
public String getOAuth2ErrorCode() {
145+
return HttpStatus.FORBIDDEN.getReasonPhrase();
146+
}
147+
148+
@Override
149+
public int getHttpErrorCode() {
150+
return HttpStatus.FORBIDDEN.value();
151+
}
152+
}
153+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.minbox.framework.api.boot.sample;
2+
3+
import com.fasterxml.jackson.core.JsonGenerator;
4+
import org.minbox.framework.api.boot.plugin.oauth.exception.ApiBootOAuth2Exception;
5+
import org.minbox.framework.api.boot.plugin.oauth.response.AuthorizationDeniedResponse;
6+
import org.springframework.stereotype.Component;
7+
8+
/**
9+
* 自定义认证错误格式化响应 {@link AuthorizationDeniedResponse}使用示例
10+
*
11+
* @author 恒宇少年
12+
*/
13+
@Component
14+
public class CustomAuthorizationDeniedResponse implements AuthorizationDeniedResponse {
15+
@Override
16+
public void serializeResponse(ApiBootOAuth2Exception e, JsonGenerator generator) {
17+
try {
18+
generator.writeObjectField("code", e.getHttpErrorCode());
19+
generator.writeObjectField("message", e.getMessage());
20+
} catch (Exception ex) {
21+
ex.printStackTrace();
22+
}
23+
}
24+
}

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@
1818
<version>${revision}</version>
1919
<name>api-boot</name>
2020
<properties>
21-
<revision>2.2.2-SNAPSHOT</revision>
21+
<revision>2.2.3-SNAPSHOT</revision>
2222
<maven-compiler-plugin.version>3.5.1</maven-compiler-plugin.version>
2323
<jdk.version>1.8</jdk.version>
2424
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
2525
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
2626
</properties>
2727
<description>
2828
ApiBoot是一款基于SpringBoot1.x、2.x的接口服务集成基础框架,
29-
内部提供了第三方框架的封装集成,让接口开发者可以选择性完成开箱即用
29+
内部提供了第三方框架的封装集成,让接口开发者可以选择性使用starter完成开箱即用
3030
不再为搭建接口框架而犯愁,从而极大的提高开发效率。
3131
</description>
3232
<url>https://gitee.com/minbox-projects/api-boot</url>

0 commit comments

Comments
 (0)