【发布时间】:2021-01-27 03:01:32
【问题描述】:
我正在尝试在我的SpringBoot 2.2.6 REST 后端实现JWT Token based,我想:
- 执行FIRST 身份验证从
UserDetailService检索用户 - 如果身份验证顺利生成
JWT Token - 对于以下访问验证令牌无需访问数据库
这是我的身份验证过滤器:
public class JWTAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
protected JWTAuthenticationFilter(String defaultFilterProcessesUrl) {
super(defaultFilterProcessesUrl);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
ApplicationUser creds = new ObjectMapper().readValue(request.getInputStream(), ApplicationUser.class);
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
creds.getUsername(), creds.getPassword(), Collections.emptyList());
// retrieve user from my userdetailservice
return getAuthenticationManager().authenticate(authToken);
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult)
throws IOException, ServletException {
super.successfulAuthentication(request, response, chain, authResult);
// if Authentication goes well I generate the token and send it through the header response
response.addHeader("Bearer ", "token");
}
}
这是我的SecurityConfig:
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final ApplicationUserDetailService userDetailService;
private final RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailService).passwordEncoder(new BCryptPasswordEncoder());
}
@Bean
public JWTAuthenticationFilter authenticationTokenFilterBean() throws Exception {
JWTAuthenticationFilter jwtAuthenticationFilter = new JWTAuthenticationFilter("/login");
jwtAuthenticationFilter.setAuthenticationManager(authenticationManager);
...
return jwtAuthenticationFilter;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors().and()
.csrf().disable()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(authenticationTokenFilterBean(), BasicAuthenticationFilter.class);
}
这个配置正确吗??放置另一个 OncePerRequestFilter 来解析令牌(如果存在)是个好主意,或者我应该在上面的身份验证过滤器中执行所有操作?
谢谢
------------更新---------- ----
我将尝试放置一个过滤器来检查令牌是否存在,如果存在,则对其进行验证 - 提取用户和角色并将 UsernamePasswordAuthenticationToken 放入上下文中。因此我重写AbstractAuthenticationProcessingFilter的doFilter方法如下:
public class JWTAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
protected JWTAuthenticationFilter(String defaultFilterProcessesUrl) {
super(defaultFilterProcessesUrl);
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
String header = request.getHeader(SecurityConstant.AUTH);
if (header == null || !header.startsWith(SecurityConstant.TOKEN_PREFIX)) {
filterChain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
filterChain.doFilter(request, response);
}
但是,测试它,如果我调用私有路径(需要身份验证)doFilter 方法会触发两次......
我把那个过滤器放在BasicAuthenticationFilter.class..之前有没有人可以解释我怎么了??
谢谢
【问题讨论】:
标签: rest spring-security jwt