java - 在 Spring Security 中未触发 JWT 身份验证过滤器
问题描述
我为我的 Spring Rest 后端创建了一个 JWT 身份验证过滤器。创建 JWT 似乎不是问题,但是在我当前的设置中,任何请求都经过身份验证,尽管客户端没有在标头中传递任何令牌,但没有请求触发 401。
我的网络安全配置:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true,
jsr250Enabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private JwtAuthenticationEntryPoint unauthorizedHandler;
private CustomUserDetailsService customUserDetailsService;
@Autowired
public WebSecurityConfig(final JwtAuthenticationEntryPoint unauthorizedHandler,
final CustomUserDetailsService customUserDetailsService) {
this.unauthorizedHandler = unauthorizedHandler;
this.customUserDetailsService = customUserDetailsService;
}
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
@Bean
public JwtAuthenticationSuccessHandler jwtAuthenticationSuccessHandler() {
return new JwtAuthenticationSuccessHandler();
}
@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
@Bean(BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* {@inheritDoc}
*/
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.cors()
.and()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.antMatcher("/api")
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
/**
* Sets security evaluation context.
*
* @return {@link SecurityEvaluationContextExtension}
*/
@Bean
public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
return new SecurityEvaluationContextExtension();
}
}
我已将其设置为所有请求都需要授权。我的 JwtAuthenticationEntryPoint 符合预期:抛出一个通用的 401 错误。
我的 JwtAuthenticationFilter:
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtTokenProvider tokenProvider;
@Autowired
private CustomUserDetailsService customUserDetailsService;
private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain
filterChain) throws ServletException, IOException {
logger.debug("Filtering request for JWT header verification");
try {
String jwt = getJwtFromRequest(request);
if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {
String username = tokenProvider.getUserIdFromJWT(jwt);
UserDetails userDetails = customUserDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken
(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception ex) {
logger.error("Could not set user authentication in security context", ex);
}
filterChain.doFilter(request, response);
}
private String getJwtFromRequest(HttpServletRequest request) {
logger.debug("Attempting to get token from request header");
String bearerToken = request.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7, bearerToken.length());
}
return null;
}
}
解决方案
发现了问题。
我必须在我的 web.xml 文件中包含对过滤器的引用,这不是使用组件扫描器自动获取的。
就像是:
<filter>
<filter-name>jwtFilter</filter-name>
<filter-class>com.path.to.JwtFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>jwtFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
推荐阅读
- javascript - Javascript中的同步调用
- node.js - Docker - Puppeteer 需要一些东西并且不会运行
- android - 在动画列表中使用动画中的图像
- synchronization - RHEL Chrony 没有输出
- nginx - 无法在 ECK 上使用 Elastic Stack 和 Filebeat 收集 Nginx 日志
- c# - 原始 UTC 值的 Postgres 时间戳和时区
- python - Python Pandas 根据最后一个元素和剩余元素将列拆分为两列
- css - 如何使用flexbox将行下方的一行中的框与两个框反转?
- c++ - std::make_tuple 和右值引用
- python - 从非数字数据训练以预测新数据集中的字符串列 - Python 机器学习模块