共计 2541 个字符,预计需要花费 7 分钟才能阅读完成。
SpringBoot 实战电商我的项目 mall(40k+star)地址:https://github.com/macrozheng/mall
摘要
在开发过程中,遇到问题,咱们常常会应用搜索引擎来查找问题的解决方案,而后予以解决。然而有些问题一时半会搜寻不到解决方案,须要本人去解决。这里分享下我解决这些问题应用的调试技巧,给大家一个解决问题的新思路!
问题形容
在《我扒了半天源码,终于找到了 Oauth2 自定义处理结果的最佳计划!》一文中,当 JWT 令牌过期或者签名不正确时,咱们想要自定义网关认证失败的返回后果。这个问题解决起来很简略,只需批改一行代码即可。然而过后查找解决方案的确破费了一番功夫,通过 DEBUG 源码才找到了 Spring Security 中提供的自定义配置,解决了该问题。上面讲讲我是如何通过 DEBUG 源码找到这个解决方案的!
解决过程
- 首先咱们须要找到一个切入点,既然问题是因为 JWT 令牌过期或者签名不正确才产生的,咱们很容易想到
RSASSAVerifier
这个要害类,它的verify()
办法是用来验证签名是否正确的,咱们能够在该办法下面打个断点 DEBUG 一下,发现程序执行过程果然会通过这里,要是签名不正确会间接返回 false;
- 这时候咱们能够查下堆栈信息,理解下这次调用的整个过程,能够看到红框以下的调用都是 WebFlux 外面的调用,没有参考意义,所以调用最早是从
NimbusReactiveJwtDecoder
类开始的;
- 咱们搜寻下
NimbusReactiveJwtDecoder
在哪里被应用到了,能够找到又一个要害类ServerHttpSecurity
,咱们在网关的平安配置ResourceServerConfig
中已经用到过它,猜测下如果 Spring Security 提供了自定义配置,那预计就在这个类外面了;
- 查看下
ServerHttpSecurity
的类正文,咱们能够发现它相当于 WebFlux 版本的 Spring Security 配置;
/**
* A {@link ServerHttpSecurity} is similar to Spring Security's {@code HttpSecurity} but for WebFlux.
* It allows configuring web based security for specific http requests. By default it will be applied
* to all requests, but can be restricted using {@link #securityMatcher(ServerWebExchangeMatcher)} or
* other similar methods.
**/
- 在咱们网关的
ResourceServerConfig
中,咱们已经调用过ServerHttpSecurity
的build()
办法,用于生成SecurityWebFilterChain
;
- 让咱们看看这个
build()
办法干了点啥,其中有段比拟要害的是它调用了OAuth2ResourceServerSpec
类的configure()
办法;
- 而
OAuth2ResourceServerSpec
类的configure()
办法又调用了JwtSpec
类的configure()
办法;
- 这个
JwtSpec
对象是不会为空的,因为咱们在ResourceServerConfig
中调用了OAuth2ResourceServerSpec
类的jwt()
办法创立了它;
JwtSpec
类的configure
办法很要害,应用过滤器来进行认证是 Spring Security 实现认证的老套路了,于是咱们找到了默认的认证过滤器BearerTokenAuthenticationWebFilter
;
BearerTokenAuthenticationWebFilter
应用了OAuth2ResourceServerSpec
中的entryPoint
来解决认证失败,默认实现为BearerTokenServerAuthenticationEntryPoint
;
- 之后咱们在
BearerTokenAuthenticationWebFilter
的filter()
办法,BearerTokenServerAuthenticationEntryPoint
的commence()
办法上别离打个断点,来验证下,调用过程中都通过了,完全正确;
- 也就是说咱们只有把默认的认证失败处理器换成咱们自定义的就行了,间接通过如下代码把
OAuth2ResourceServerSpec
中的entryPoint
来设置成自定义的即可。
/**
* 资源服务器配置
* Created by macro on 2020/6/19.
*/
@AllArgsConstructor
@Configuration
@EnableWebFluxSecurity
public class ResourceServerConfig {
private final RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
// 省略若干代码...
// 自定义解决 JWT 申请头过期或签名谬误的后果
http.oauth2ResourceServer().authenticationEntryPoint(restAuthenticationEntryPoint);
// 省略若干代码...
return http.build();}
}
总结
对于一时找不到解决办法的问题,我举荐应用 DEBUG 源码的形式来解决。首先寻找一个突破口,能够从你相熟的一些类中去寻找一个必定会执行的办法,而后打断点,进行 DEBUG,从调用的栈信息中查找出要害的类,之后通过这些要害类顺藤摸瓜就能找解决办法了!
我的项目源码地址
https://github.com/macrozheng…
本文 GitHub https://github.com/macrozheng/mall-learning 曾经收录,欢送大家 Star!
正文完