Spring Security Oauth2 自定义 OAuth2 Exception


声明:本文转载自https://my.oschina.net/merryyou/blog/1819572,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

付出就要得到回报,这种想法是错的。

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/spring-security-OAuth208.png

前言

在使用Spring Security Oauth2登录和鉴权失败时,默认返回的异常信息如下

{   "error": "unauthorized",   "error_description": "Full authentication is required to access this resource" } 

。它与我们自定义返回信息不一致,并且描述信息较少。那么如何自定义Spring Security Oauth2异常信息呢,下面我们简单实现以下。格式如下:

 { "error": "400", "message": "坏的凭证", "path": "/oauth/token", "timestamp": "1527432468717" } 

自定义登录失败异常信息

新增CustomOauthException

  • 添加自定义异常类,指定json序列化方式
@JsonSerialize(using = CustomOauthExceptionSerializer.class) public class CustomOauthException extends OAuth2Exception {     public CustomOauthException(String msg) {         super(msg);     } } 

新增CustomOauthExceptionSerializer

  • 添加CustomOauthException的序列化实现
public class CustomOauthExceptionSerializer extends StdSerializer<CustomOauthException> {     public CustomOauthExceptionSerializer() {         super(CustomOauthException.class);     }      @Override     public void serialize(CustomOauthException value, JsonGenerator gen, SerializerProvider provider) throws IOException {         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();          gen.writeStartObject();         gen.writeStringField("error", String.valueOf(value.getHttpErrorCode()));         gen.writeStringField("message", value.getMessage()); //        gen.writeStringField("message", "用户名或密码错误");         gen.writeStringField("path", request.getServletPath());         gen.writeStringField("timestamp", String.valueOf(new Date().getTime()));         if (value.getAdditionalInformation()!=null) {             for (Map.Entry<String, String> entry : value.getAdditionalInformation().entrySet()) {                 String key = entry.getKey();                 String add = entry.getValue();                 gen.writeStringField(key, add);             }         }         gen.writeEndObject();     } }  

添加CustomWebResponseExceptionTranslator

  • 添加CustomWebResponseExceptionTranslator,登录发生异常时指定exceptionTranslator
public class CustomOauthExceptionSerializer extends StdSerializer<CustomOauthException> {     public CustomOauthExceptionSerializer() {         super(CustomOauthException.class);     }      @Override     public void serialize(CustomOauthException value, JsonGenerator gen, SerializerProvider provider) throws IOException {         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();          gen.writeStartObject();         gen.writeStringField("error", String.valueOf(value.getHttpErrorCode()));         gen.writeStringField("message", value.getMessage()); //        gen.writeStringField("message", "用户名或密码错误");         gen.writeStringField("path", request.getServletPath());         gen.writeStringField("timestamp", String.valueOf(new Date().getTime()));         if (value.getAdditionalInformation()!=null) {             for (Map.Entry<String, String> entry : value.getAdditionalInformation().entrySet()) {                 String key = entry.getKey();                 String add = entry.getValue();                 gen.writeStringField(key, add);             }         }         gen.writeEndObject();     } }  

修改MerryyouAuthorizationServerConfig

  • 指定自定义customWebResponseExceptionTranslator
@Override     public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {         endpoints.tokenStore(tokenStore)                 .authenticationManager(authenticationManager)                 .userDetailsService(userDetailsService);         //扩展token返回结果         if (jwtAccessTokenConverter != null && jwtTokenEnhancer != null) {             TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();             List<TokenEnhancer> enhancerList = new ArrayList();             enhancerList.add(jwtTokenEnhancer);             enhancerList.add(jwtAccessTokenConverter);             tokenEnhancerChain.setTokenEnhancers(enhancerList);             //jwt             endpoints.tokenEnhancer(tokenEnhancerChain)                     .accessTokenConverter(jwtAccessTokenConverter);         }         endpoints.exceptionTranslator(customWebResponseExceptionTranslator);     }  

自定义Token异常信息

添加AuthExceptionEntryPoint

  • 自定义AuthExceptionEntryPoint用于tokan校验失败返回信息
public class AuthExceptionEntryPoint implements AuthenticationEntryPoint {       @Override     public void commence(HttpServletRequest request, HttpServletResponse response,                          AuthenticationException authException)             throws  ServletException {          Map map = new HashMap();         map.put("error", "401");         map.put("message", authException.getMessage());         map.put("path", request.getServletPath());         map.put("timestamp", String.valueOf(new Date().getTime()));         response.setContentType("application/json");         response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);         try {             ObjectMapper mapper = new ObjectMapper();             mapper.writeValue(response.getOutputStream(), map);         } catch (Exception e) {             throw new ServletException();         }     } } 

添加CustomAccessDeniedHandler

  • 授权失败(forbidden)时返回信息
@Slf4j @Component("customAccessDeniedHandler") public class CustomAccessDeniedHandler implements AccessDeniedHandler {      @Autowired     private ObjectMapper objectMapper;      @Override     public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {         response.setContentType("application/json;charset=UTF-8");             Map map = new HashMap();             map.put("error", "400");             map.put("message", accessDeniedException.getMessage());             map.put("path", request.getServletPath());             map.put("timestamp", String.valueOf(new Date().getTime()));             response.setContentType("application/json");             response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);             response.getWriter().write(objectMapper.writeValueAsString(map));     } } 

修改MerryyouResourceServerConfig

    @Override     public void configure(ResourceServerSecurityConfigurer resources) throws Exception {         resources.authenticationEntryPoint(new AuthExceptionEntryPoint())         .accessDeniedHandler(CustomAccessDeniedHandler);     } 

效果如下

登录异常

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/security/spring-security-oauth209.gif

token异常

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/security/spring-security-oauth210.gif

禁止访问

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/security/spring-security-oauth211.gif

token失效

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/security/spring-security-oauth212.gif

代码下载

推荐文章

  1. Java创建区块链系列
  2. Spring Security源码分析系列
  3. Spring Data Jpa 系列
  4. 【译】数据结构中关于树的一切(java版)
  5. SpringBoot+Docker+Git+Jenkins实现简易的持续集成和持续部署

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/wechat/xiaochengxu.png

本文发表于2018年05月28日 08:00
(c)注:本文转载自https://my.oschina.net/merryyou/blog/1819572,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 4062 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1