ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring Security OAuth2 授权失败(401)

2021-07-06 13:29:57  阅读:286  来源: 互联网

标签:OAuth2 Spring 校验 接口 access token 401 new public


Spring Cloud架构中采用Spring Security OAuth2作为权限控制,关于OAuth2详细介绍可以参考 http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html

项目中采用OAuth2四种模式中的两种,Password模式和Client模式, Password模式用于控制用户的登录,Client模式用于控制后端服务相互调用。

权限架构调整后在近期发现一些问题,由于网上资料不多,只能单步调试方式看源码 (其实带着问题看源码是最好的方式)。现在将问题和解决方案整理如下:

一、免登录接口校验token问题
问题:APP端反馈,一些免登录接口会校验token

   详细:经过测试发现,免登录接口 如果传了access_token会对token合法性就行校验,如果不传接口不会校验,这导致了免登录接口的过期token会报错

  排查:经过查看源码发现spring-security-oauth2的过滤器 OAuth2AuthenticationProcessingFilter 会对请求进行拦截,(具体源码就不截图了)

如果存在access_token 则会根据userInfoEndpointUrl去认证服务器上校验token信息,
如果不存在access_token 则会继续执行spring-security的拦截器FilterSecurityInterceptor。 FilterSecurityInterceptor对路径是否需要授权,已经授权是否通过做校验~  
解决: 可以采用过滤器在执行到核心过滤器OAuth2AuthenticationProcessingFilter ,将不需要授权的请求头中的access_token过滤掉。或者APP免登录接口不传token

              最终采用的是后者

二、Token失效返回的是状态401的错误
1、问题: APP端反馈,传递失效access_token,返回401状态,期望是200同时以错误码方式提示token失效。

  排查:经过单步调试分析源码发现,token失效后,认证服务器会抛出异常,同时响应给资源服务器,资源服务发现认证服务器的错误后会抛出InvalideException。

            抛出的异常会经过默认的DefaultWebResponseExceptionTranslator 处理然后 Reseponse给Client端。

  解决:通过上面的分析指导。最后的异常是在DefaultWebResponseExceptionTranslator 处理的,所以只需要

自定义实现类Implements WebResponseExceptionTranslator 接口处理异常装换逻辑,
使得自定义的类生效
 (1)自定义异常转换类

复制代码
1 @Slf4j
2 public class Auth2ResponseExceptionTranslator implements WebResponseExceptionTranslator {
3
4 @Override
5 public ResponseEntity translate(Exception e) {
6 log.error(“Auth2异常”, e);
7 Throwable throwable = e.getCause();
8 if (throwable instanceof InvalidTokenException) {
9 log.info(“token失效:{}”, throwable);
10 return new ResponseEntity(new Message<>(ServerConstant.INVALID_TOKEN.getMsg(), ServerConstant.INVALID_TOKEN.getCode()), HttpStatus.OK);
11 }
12 return new ResponseEntity(new Message(e.getMessage(), String.valueOf(HttpStatus.METHOD_NOT_ALLOWED.value())), HttpStatus.METHOD_NOT_ALLOWED);
13 }
14 }
复制代码
(2)资源服务器中使得自定义类生效

复制代码
1 @Configuration
2 @EnableResourceServer
3 public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
4
5
6 @Override
7 public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
// 定义异常转换类生效
8 AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
9 ((OAuth2AuthenticationEntryPoint) authenticationEntryPoint).setExceptionTranslator(new Auth2ResponseExceptionTranslator());
10 resources.authenticationEntryPoint(authenticationEntryPoint);
11 }
12
13
14 @Override
15 public void configure(HttpSecurity http) throws Exception {
16 http
17 .csrf().disable()
18 .exceptionHandling()
// 定义的不存在access_token时候响应
19 .authenticationEntryPoint(new SecurityAuthenticationEntryPoint())
20 .and()
21 .authorizeRequests().antMatchers("//").permitAll()
22 .anyRequest().authenticated()
23 .and()
24 .httpBasic().disable();
25 }
复制代码

2、问题:测试发现授权接口,当请求参数中不存在access_token时发现接口返回错误信息:
{“timestamp”:1539337154336,“status”:401,“error”:“Unauthorized”,“message”:“No message available”,“path”:"/app/businessCode/list"}

  排查:经过前面的分析发现,上面提到Security的FilterSecurityInterceptor对OAuth2中返回的信息和本身配置校验后,抛出AccessDenyException。

  解决:经过上面的几个问题的处理,发现思路还是一样的,需要定义响应结果,

              即1、自定义响应处理逻辑SecurityAuthenticationEntryPoint 2、自定义处理逻辑SecurityAuthenticationEntryPoint生效(见上面的配置)

 SecurityAuthenticationEntryPoint具体实现:

复制代码
1 @Slf4j
2 public class SecurityAuthenticationEntryPoint implements AuthenticationEntryPoint {
3
4 @Override
5 public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
6 log.error(“Spring Securtiy异常”, authException);
7 response.setCharacterEncoding(“UTF-8”);
8 response.setContentType(“application/json; charset=utf-8”);
9 PrintWriter out = response.getWriter();
10 out.print(JSON.toJSONString(new Message<>(ServerConstant.INVALID_TOKEN.getMsg(), ServerConstant.INVALID_TOKEN.getCode())));
11 }
12 }
复制代码

标签:OAuth2,Spring,校验,接口,access,token,401,new,public
来源: https://blog.csdn.net/qq_18671415/article/details/118518450

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有