前言
在整合Spring Security Oauth2的时候,获取token的接口/oauth/token的返回内容格式为固定的,如下图所示:
而token过期或者无效的返回参数格式如下图所示:
实际在我们的项目中有时候会要求自定义返回内容格式,下面分别介绍获取token和token失效/过期的自定义返回内容格式。
自定义获取token接口的参数格式
1、创建接收获取token接口返回参数的实体
@Data
public class OauthResult {
private String code;
private String mesg;
}
@JsonSerialize(using = ResponseSerializer.class)
@Data
public class OauthResponse extends OauthResult{
private Object data;
}
2、创建获取token接口返回值的转换类
创建一个类来完成对获取token接口的返回参数进行转换成我们自定义的格式,这里使用到了@JsonSerialize注解,该注解主要用于数据转换,不知道的可以自行百度
import com.bw.dsm.entity.OauthResponse;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import java.io.IOException;
public class ResponseSerializer extends StdSerializer<OauthResponse> {
public ResponseSerializer() {
super(OauthResponse.class);
}
@Override
public void serialize(OauthResponse value, JsonGenerator gen, SerializerProvider provider) throws IOException {
OAuth2AccessToken oAuth2AccessToken = (OAuth2AccessToken) value.getData();
gen.writeStartObject();
if (oAuth2AccessToken != null){
gen.writeStringField("code", value.getCode());
gen.writeStringField("mesg", value.getMesg());
gen.writeObjectFieldStart("data");
gen.writeStringField("accessToken", oAuth2AccessToken.getValue());
gen.writeNumberField("expiresIn",oAuth2AccessToken.getExpiresIn());
gen.writeEndObject();
} else {
gen.writeStringField("code", "1");
gen.writeStringField("mesg", "获取token失败");
}
gen.writeEndObject();
}
}
3、新建切面类,将ResponseEntity进行重新组织,改变返回值
自定义切点,对postAccessToken方法进行增强,该方法是/oauth/token接口的返回方法,在这个方法的基础上改变返回值即可。
import com.bw.dsm.entity.OauthResponse;
import com.bw.dsm.util.AES128Util;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class AuthTokenAspect {
private Logger logger = LoggerFactory.getLogger(getClass());
/// @Around是可以改变controller返回值的
@Around("execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))")
public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable {
// 放行
OauthResponse response = new OauthResponse();
ObjectMapper mapper = new ObjectMapper();
try {
Object proceed = pjp.proceed();
if (proceed != null) {
ResponseEntity<OAuth2AccessToken> responseEntity = (ResponseEntity<OAuth2AccessToken>)proceed;
OAuth2AccessToken body = responseEntity.getBody();
if (responseEntity.getStatusCode().is2xxSuccessful()) {
response.setCode("0");
response.setMesg("");
response.setData(body);
} else {
logger.error("error:{}", responseEntity.getStatusCode().toString());
response.setCode("1");
response.setMesg("获取token失败");
}
}
} catch (Exception e){
response.setCode("1");
response.setMesg("获取token失败");
}
String result = mapper.writeValueAsString(response);
return ResponseEntity
.status(200)
.body(AES128Util.JiaMi(result));
}
}
我这里还另外对返回值进行了加密,如果不需要加密则直接返回response,即:
return ResponseEntity
.status(200)
.body(response);
这样,返回格式就成了我们自定义的格式了,下面可以看下未加密的自定义返回格式:
获取token接口调用成功:
获取token接口调用失败:
自定义token过期/无效的返回参数格式
1、在配置资源服务器的配置类中添加拦截
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
// 自定义token失效/错误返回信息
OAuth2AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
authenticationEntryPoint.setExceptionTranslator(new CustomExceptionTranslator());
resources.authenticationEntryPoint(authenticationEntryPoint);
}
}
其他配置省略。按照各自业务需求来,这里只介绍自定义token过期/无效的返回参数格式。
2、自定义接收token无效/过期的错误信息转换类
import com.bw.dsm.util.AES128Util;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
public class CustomExceptionTranslator extends DefaultWebResponseExceptionTranslator {
@Override
public ResponseEntity translate(Exception e) throws Exception {
ResponseEntity translate = super.translate(e);
ObjectMapper mapper = new ObjectMapper();
OAuth2Exception body = (OAuth2Exception) translate.getBody();
CustomOauthException customOauthException = new CustomOauthException(body.getMessage(), body.getOAuth2ErrorCode(), String.valueOf(body.getHttpErrorCode()));
// ResponseEntity response = new ResponseEntity<>(customOauthException, translate.getHeaders(), translate.getStatusCode());
return ResponseEntity
.status(translate.getStatusCode())
.header(String.valueOf(translate.getHeaders()))
.body(AES128Util.JiaMi(mapper.writeValueAsString(customOauthException)));
}
}
同样的这里我也将返回参数加密处理,如果不需要加密,如下所示:
public class CustomExceptionTranslator extends DefaultWebResponseExceptionTranslator {
@Override
public ResponseEntity translate(Exception e) throws Exception {
ResponseEntity translate = super.translate(e);
ObjectMapper mapper = new ObjectMapper();
OAuth2Exception body = (OAuth2Exception) translate.getBody();
CustomOauthException customOauthException = new CustomOauthException(body.getMessage(), body.getOAuth2ErrorCode(), String.valueOf(body.getHttpErrorCode()));
ResponseEntity response = new ResponseEntity<>(customOauthException, translate.getHeaders(), translate.getStatusCode());
return response;
}
}
3、创建自定义token无效/过期返回参数格式类
@JsonSerialize(using = CustomOauthExceptionSerializer.class)
public class CustomOauthException extends OAuth2Exception {
private String code;
private String mesg;
public CustomOauthException(String msg, String code, String mesg){
super(msg);
this.code = code;
this.mesg = mesg;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMasg() {
return mesg;
}
public void setMasg(String mesg) {
this.mesg = mesg;
}
}
4、token无效或过期返回值转换类
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
public class CustomOauthExceptionSerializer extends StdSerializer {
public CustomOauthExceptionSerializer() {
super(CustomOauthException.class);
}
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeObjectField("code","1");
gen.writeObjectField("mesg","token无效或已过期");
gen.writeEndObject();
}
}
这样,返回格式就成了我们自定义的格式了,下面可以看下未加密的自定义返回格式:
token无效返回:
版权声明:程序员胖胖胖虎阿 发表于 2022年8月31日 下午3:40。
转载请注明:自定义spring security oauth2 /oauth/token以及token失效/过期的返回内容格式 | 胖虎的工具箱-编程导航
转载请注明:自定义spring security oauth2 /oauth/token以及token失效/过期的返回内容格式 | 胖虎的工具箱-编程导航
相关文章
暂无评论...