hol*_*laa 9 java spring-security spring-boot
我正在使用 Spring security 和 jwt ,但是配置文件中有一些我不理解的东西(JWT 上所有教程中的配置相同),这就是为什么要在之前添加自定义 jwt 过滤器,UsernamePasswordAuthenticationFilter因为我已经有一个公共基于项目某处的用户名和密码的身份验证控制器,为什么不以其他顺序添加它?
@Bean
public JwtAuthTokenFilter authenticationJwtTokenFilter() {
return new JwtAuthTokenFilter();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling().authenticationEntryPoint((AuthenticationEntryPoint) unauthorizedHandler)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore((Filter) authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
Run Code Online (Sandbox Code Playgroud)
ale*_*ria 12
TL;博士;
我相信这只是互联网上某人碰巧选择并在某处共享他/她的代码的随机过滤器,从那时起就一直采用这种方式。
对于好奇的人
我亲自查看了 Spring Security 源代码,发现 Spring 应用程序上下文中的过滤器及其各自的@Orders 如下:
org.springframework.security.web.access.channel.ChannelProcessingFilter -> 100
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter -> 300
org.springframework.security.web.context.SecurityContextPersistenceFilter -> 400
org.springframework.security.web.header.HeaderWriterFilter -> 500
org.springframework.web.filter.CorsFilter -> 600
org.springframework.security.web.csrf.CsrfFilter -> 700
org.springframework.security.web.authentication.logout.LogoutFilter -> 800
org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter -> 900
org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationRequestFilter -> 1000
org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter -> 1100
org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter -> 1200
org.springframework.security.cas.web.CasAuthenticationFilter -> 1300
org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter -> 1400
org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter -> 1500
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter -> 1600
org.springframework.security.openid.OpenIDAuthenticationFilter -> 1800
org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter -> 1900
org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter -> 2000
org.springframework.security.web.session.ConcurrentSessionFilter -> 2100
org.springframework.security.web.authentication.www.DigestAuthenticationFilter -> 2200
org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter -> 2300
org.springframework.security.web.authentication.www.BasicAuthenticationFilter -> 2400
org.springframework.security.web.savedrequest.RequestCacheAwareFilter -> 2500
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter -> 2600
org.springframework.security.web.jaasapi.JaasApiIntegrationFilter -> 2700
org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter -> 2800
org.springframework.security.web.authentication.AnonymousAuthenticationFilter -> 2900
org.springframework.security.oauth2.client.web.OAuth2AuthorizationCodeGrantFilter -> 3000
org.springframework.security.web.session.SessionManagementFilter -> 3100
org.springframework.security.web.access.ExceptionTranslationFilter -> 3200
org.springframework.security.web.access.intercept.FilterSecurityInterceptor -> 3300
org.springframework.security.web.authentication.switchuser.SwitchUserFilter -> 3400
Run Code Online (Sandbox Code Playgroud)
请注意,顺序值越小,过滤器的优先级越高。
但这些都是Spring注册的过滤器。另一方面,Spring Security 是一个内部包含多个过滤器的单个过滤器链,仅包含其中的一些过滤器,它们是(按优先级顺序):
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CorsFilter
LogoutFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
Run Code Online (Sandbox Code Playgroud)
您可以通过在 Spring Security 配置中将调试标志设置为 true 来获取此列表
@EnableWebSecurity(debug = true)
Run Code Online (Sandbox Code Playgroud)
自定义 Jwt 过滤器放在哪里?
我个人会将自定义 Jwt Filter 放置在 之前ExceptionTranslationFilter和之后FilterSecurityInterceptor,形成以下链:
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CorsFilter
LogoutFilter
<------ Here's where the UsernamePasswordAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
JwtAuthTokenFilter <------ Here's your filter.
FilterSecurityInterceptor
]
Run Code Online (Sandbox Code Playgroud)
您会看到这样做的动机是让 Spring 安全异常处理程序驻留在其中ExceptionTranslatorFilter按原样处理您的异常。因为如果您将过滤器放置在 的位置UsernamePasswordAuthenticationFilter,则过滤器将看不到过滤器抛出的任何可能的异常ExceptionTranslatorFilter,相反,它将一直返回到throwable()Tomcat 的方法org.apache.catalina.core.StandardHostValve(如果您使用 Tomcat 作为 servlet impl) .,显然),它要做的是将您的请求重定向到默认错误路径,即/error.
这就是有趣的地方,当您的过滤器抛出异常时,该过滤器应该拦截进入您的应用程序的任何请求(例如),现在将发出/hello对预定义错误路径(让我们假设)的后续请求。/error幸运的是,如果您的配置没有碰巧“允许”该路径HttpSecurity,接下来会发生以下一系列事件:
/errorOncePerRequestFilter(我认为会这样),它将不会再次被过滤,因为它在上一次传递中已被标记为“已过滤”。FilterSecurityInterceptorAccessDecisionVoters,这将立即将不熟悉的/error请求投票为未经身份验证,抛出AccessDeniedException并结束。ExceptionTranslationFilter将看到 this AccessDeniedException,将其评估为常规访问拒绝,并AuthenticationEntryPoint.commence使用AccessDeniedException第三个参数调用 。sendError在该方法中调用,并且您的客户端将收到此响应。那么,这是怎么回事,我在过滤器中阻止了请求,而客户端收到了错误响应?
问题是,客户端收到的消息不是为您的请求或错误生成的,而是为对路径的请求/error和FilterSecurityInterceptor.
那你该怎么办 ?
我谦虚地建议,将您的过滤器放在JwtAuthTokenFilter安全过滤器链中的最后两个过滤器之间,并且您可能抛出的错误将由默认的 Spring Security 错误解析器处理,并且您将为服务器节省 和 之间的StandardHostValve往返FilterSecurityInterceptor。
http.addFilterAfter(authenticationJwtTokenFilter(), ExceptionTranslationFilter.class);
Run Code Online (Sandbox Code Playgroud)
或者不这样做,客户端最终会收到错误。
| 归档时间: |
|
| 查看次数: |
3760 次 |
| 最近记录: |