Spring JWT过滤器配置

时间:2016-03-25 12:05:20

标签: spring spring-mvc spring-security jwt

我想添加一个过滤器来使用令牌验证用户身份。我通过添加两个过滤器来实现这一目标:

public class JwtFilter extends GenericFilterBean {

private TokenAuthenticationService authenticationService;

public JwtFilter(TokenAuthenticationService service) {
    this.authenticationService = service;
}

public JwtFilter() {
}

@Override
public void doFilter(final ServletRequest request,
                     final ServletResponse response,
                     final FilterChain chain) throws IOException, ServletException {
    System.out.println("JwtFilter.doFilter");
    SecurityContextHolder.getContext().setAuthentication(
            authenticationService.getAuthentication((HttpServletRequest) request));
    chain.doFilter(request, response);
}

之后我创建了第二个Filter,以授权用户:

public class StatelessLoginFilter extends AbstractAuthenticationProcessingFilter {


private final TokenAuthenticationService tokenAuthenticationService;
private final UserDetailsService userService;

public StatelessLoginFilter(String urlMapping, TokenAuthenticationService tokenAuthenticationService,
                            UserDetailsService userDetailsService, AuthenticationManager authManager) {
    super(new AntPathRequestMatcher(urlMapping));
    this.userService = userDetailsService;
    this.tokenAuthenticationService = tokenAuthenticationService;
    setAuthenticationManager(authManager);
}

@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
    System.out.println("StatelessLoginFilter.successfulAuthentication");
    // Lookup the complete User object from the database and create an Authentication for it
    final User authenticatedUser = (User) userService.loadUserByUsername(authResult.getName());
    final UserAuthentication userAuthentication = new UserAuthentication(authenticatedUser);

    // Add the custom token as HTTP header to the response
    tokenAuthenticationService.addAuthentication(response, userAuthentication);

    // Add the authentication to the Security context
    SecurityContextHolder.getContext().setAuthentication(userAuthentication);
}

@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException {
    System.out.println("StatelessLoginFilter.attemptAuthentication");
    final User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
    final UsernamePasswordAuthenticationToken loginToken = new U

sernamePasswordAuthenticationToken(
                user.getUsername(), user.getPassword());
        return getAuthenticationManager().authenticate(loginToken);
   }
}

这是我的SecurityConfiguration:

    @Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private TokenAuthenticationService tokenAuthenticationService;



    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()

                .authorizeRequests()
                .antMatchers("/user/**").authenticated()
                .anyRequest().permitAll().and()
                .addFilterBefore(new StatelessLoginFilter("/login", tokenAuthenticationService, userDetailsService, authenticationManager()), UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(new JwtFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception{
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
     auth .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }

    @Override
    protected UserDetailsService userDetailsService() {
        return userDetailsService;
    }

}

现在,当我向“/ login”发送请求时,我得到404错误页面。 Trully,我没有映射控制器,但在安全性中,安全配置中有一个URL映射。正如我在文档中所读到的那样:

  

使用特定模式创建匹配器,该模式将以不区分大小写的方式匹配所有HTTP方法。

另外,你可以看到System.out.println()行。我在这里放置断点,但执行不到达这一行。我不确定我是否正确注册了这个过滤器。我的代码主要基于此存储库:https://github.com/BranislavLazic/angular-security

1 个答案:

答案 0 :(得分:1)

Springboot JWT Starter是使用JWT启动无状态springboot应用程序的好方法。

如下所示编写SecurityConfiguration。

protected void configure(HttpSecurity http) throws Exception {
    http
            .csrf()
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
            .sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS ).and()
            .exceptionHandling().authenticationEntryPoint( restAuthenticationEntryPoint ).and()
            .addFilterBefore(jwtAuthenticationTokenFilter(), BasicAuthenticationFilter.class)
            .authorizeRequests()
                .antMatchers("/", "/index.html", "/login.html", "/home.html").permitAll()
              .anyRequest()
                .authenticated().and()
            .formLogin()
                .successHandler(authenticationSuccessHandler)
                .failureHandler(authenticationFailureHandler).and()
            .logout()
                .addLogoutHandler(jwtLogoutHandler())
                .logoutSuccessHandler((new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK))) ;
}

过滤

@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

    String authToken = getToken( request );
    // get username from token
    String username = tokenHelper.getUsernameFromToken( authToken );
    if ( username != null ) {
        // get user
        UserDetails userDetails = userDetailsService.loadUserByUsername( username );
        // create authentication
        TokenBasedAuthentication authentication = new TokenBasedAuthentication( userDetails );

        authentication.setToken( authToken );
        authentication.setAuthenticated( true );
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }

    chain.doFilter(request, response);
}

有关详细信息,请查看源代码: https://github.com/bfwg/springboot-jwt-starter/blob/master/src/main/java/com/bfwg/security/auth/TokenAuthenticationFilter.java