赞
踩
OAuth 2.0是用于授权的行业标准协议。OAuth 2.0为简化客户端开发提供了特定的授权流,包括Web应用、桌面应用、移动端应用等。
启动这三个服务 api远程调用服务 auth 认证服务 gateway 网关服务
http://localhost:9201/auth/oauth/token
首先源代码
我们进行改造。其实差不多的就是重写该方法,目的是我们将输出的数据封装到我们自定义返回类型中的data中去
@RestController @RequestMapping("/oauth") public class AuthController { @Autowired private TokenEndpoint tokenEndpoint; private Set<HttpMethod> allowedRequestMethods; /** * Oauth2登录认证 */ @RequestMapping(value = "/token", method = RequestMethod.POST) public CommonResult<Oauth2TokenDto> postAccessToken(Principal principal, @RequestParam Map<String, String> parameters) throws HttpRequestMethodNotSupportedException { if (!this.allowedRequestMethods.contains(HttpMethod.POST)) { return CommonResult.failed("请求方法必须是POST"); } OAuth2AccessToken oAuth2AccessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody(); Oauth2TokenDto oauth2TokenDto = Oauth2TokenDto.builder() .token(oAuth2AccessToken.getValue()) .refreshToken(oAuth2AccessToken.getRefreshToken().getValue()) .expiresIn(oAuth2AccessToken.getExpiresIn()) .tokenHead("Bearer ").build(); return CommonResult.success(oauth2TokenDto); } }
调用接口后:
先看下代码分析
当我们输错密码,再次调用登录认证接口时,发现认证失败的结果也统一了。
怎么弄的?上代码
看了源码,发现异常处理都是有这个类OAuth2Exception去处理,这时候我们自定义异常处理类去接受即可。
401
;首先看代码
打断点发现 这个格式都是自己自定义的
{
"code": 401,
"message": "暂未登录或token已经过期",
"data": "Jwt expired at 2022-07-27T08:47:51Z"
}
明明就是个白名单接口,只不过携带的token不对就不让访问了,显然有点不合理。如何解决呢,我们先看看不带token访问怎么样;
其实我们只要在Oauth2默认的认证过滤器前面再加个过滤器,如果是白名单接口,直接移除认证头即可,首先定义好我们的过滤器;
/** * 白名单路径访问时需要移除JWT请求头 * Created by hjt on 2020/7/24. */ @Component public class IgnoreUrlsRemoveJwtFilter implements WebFilter { @Autowired private IgnoreUrlsConfig ignoreUrlsConfig; @Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); URI uri = request.getURI(); PathMatcher pathMatcher = new AntPathMatcher(); //白名单路径移除JWT请求头 List<String> ignoreUrls = ignoreUrlsConfig.getUrls(); for (String ignoreUrl : ignoreUrls) { if (pathMatcher.match(ignoreUrl, uri.getPath())) { //请求不带Authorization request = exchange.getRequest().mutate().header("Authorization", "").build(); exchange = exchange.mutate().request(request).build(); return chain.filter(exchange); } } return chain.filter(exchange); } }
然后把这个过滤器配置到默认的认证过滤器之前即可,在ResourceServerConfig中进行配置;
/** * 资源服务器配置 * Created by hjt on 2020/6/19. */ @AllArgsConstructor @Configuration @EnableWebFluxSecurity public class ResourceServerConfig { private final AuthorizationManager authorizationManager; private final IgnoreUrlsConfig ignoreUrlsConfig; private final RestfulAccessDeniedHandler restfulAccessDeniedHandler; private final RestAuthenticationEntryPoint restAuthenticationEntryPoint; private final IgnoreUrlsRemoveJwtFilter ignoreUrlsRemoveJwtFilter; @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { http.oauth2ResourceServer().jwt() .jwtAuthenticationConverter(jwtAuthenticationConverter()); //自定义处理JWT请求头过期或签名错误的结果 http.oauth2ResourceServer().authenticationEntryPoint(restAuthenticationEntryPoint); //对白名单路径,直接移除JWT请求头 必须设置在默认的认证过滤器前面 http.addFilterBefore(ignoreUrlsRemoveJwtFilter, SecurityWebFiltersOrder.AUTHENTICATION); //默认的认证过滤器 http.authorizeExchange() .pathMatchers(ArrayUtil.toArray(ignoreUrlsConfig.getUrls(),String.class)).permitAll()//白名单配置 .anyExchange().access(authorizationManager)//鉴权管理器配置 .and().exceptionHandling() .accessDeniedHandler(restfulAccessDeniedHandler)//处理未授权 .authenticationEntryPoint(restAuthenticationEntryPoint)//处理未认证 .and().csrf().disable(); return http.build(); } }
个人搭建项目代码地址:
https://github.com/hongjiatao/spring-boot-anyDemo
欢迎收藏点赞三连。谢谢!有问题可以留言博主会24小时内无偿回复。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。