在Spring中为单页应用程序实现注销

时间:2017-05-16 07:45:32

标签: java spring

我正在使用 Java Web Token(JWT)在我的网络应用中进行身份验证。我想创建一个/logout Rest端点,删除客户端上的JSession cookie,使会话无效并执行其他必要的操作。

前端是用React编写的SPA。

我在扩展configure的{​​{1}}类中使用了以下WebSecurityConfig方法:

WebSecurityConfigurerAdapter

我有以下代码,但它返回@Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers("/login").permitAll() .and() .authorizeRequests() .antMatchers("/signup").permitAll() .and() .authorizeRequests() .anyRequest().authenticated() .and() .addFilterBefore( new JWTAuthenticationFilter(userDetailsServiceBean()), UsernamePasswordAuthenticationFilter.class); } 错误,路径设置为404 Not found。我希望获得/login HTTP response和一些清理。我该怎么办?

200

2 个答案:

答案 0 :(得分:0)

经过一番研究后我发现如果我想使用无状态Rest API设计,我就不应该使用任何cookie,包括JSESSIONID。

因此我将代码更改为:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .csrf().disable()
        .authorizeRequests()
            .anyRequest().authenticated()
        .and()
        .addFilterBefore(
            new JWTAuthenticationFilter(userDetailsServiceBean()),
            UsernamePasswordAuthenticationFilter.class);
}

答案 1 :(得分:0)

您可以先尝试这样的登录请求吗?首先在 WebSecurityConfig 中添加 JWTLoginFilter

从我的示例项目中粘贴代码:

http.csrf().disable() // disable csrf for our requests.
    .authorizeRequests()
    .antMatchers("/").permitAll()
    .antMatchers(HttpMethod.POST,"/login").permitAll()
    .anyRequest().authenticated()
    .and()
    // We filter the api/login requests
    .addFilterBefore(new JWTLoginFilter("/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class)
    // And filter other requests to check the presence of JWT in header
    .addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
    .addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class);

如果您的前端和后端位于同一台服务器上,您将不需要CORSFilter。

另请参阅以下JWTLoginFilter类

   public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter 
    {
    private TokenAuthenticationService tokenAuthenticationService;
    public JWTLoginFilter(String url, AuthenticationManager authenticationManager) {
     super(new AntPathRequestMatcher(url));
     setAuthenticationManager(authenticationManager);
     tokenAuthenticationService = new TokenAuthenticationService();
}

@Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
throws AuthenticationException, IOException, ServletException {
    AccountCredentials credentials = new ObjectMapper().readValue(httpServletRequest.getInputStream(), AccountCredentials.class);
    UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(credentials.getUsername(), credentials.getPassword());
    return getAuthenticationManager().authenticate(token);
}

@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication)
throws IOException, ServletException {
    String name = authentication.getName();
    tokenAuthenticationService.addAuthentication(response, name);
  }
}

AccountCredential类是简单的POJO类,包含两个字段用户名和密码,我用它来接收请求。

另请注意,我们使用的 UsernamePasswordAuthenticationFilter 需要登录请求中的两个字段'用户名'和密码'。与{"username":"user1","password":"secret1"}

一样