Java 记得我在休息时使用Spring security吗

Java 记得我在休息时使用Spring security吗,java,spring,rest,spring-security,Java,Spring,Rest,Spring Security,我需要创建“记住我”——提供休息服务。我的应用程序应该接收带有登录数据的JSON,对用户进行身份验证,并使应用程序能够记住用户。我已经编写了一些代码片段,其中包含少量模拟的@RequestMapping和简单的Spring安全配置,但是,应用程序对用户进行身份验证(因为successfulAuthentication()过滤器的方法调用)。但是,当我尝试在登录操作之后向安全url发送请求时,它返回401代码。我知道,很明显,新请求创建了一个新会话,但是有没有办法执行“记住我”行为而不在每个请求的

我需要创建“记住我”——提供休息服务。我的应用程序应该接收带有登录数据的JSON,对用户进行身份验证,并使应用程序能够记住用户。我已经编写了一些代码片段,其中包含少量模拟的@RequestMapping和简单的Spring安全配置,但是,应用程序对用户进行身份验证(因为successfulAuthentication()过滤器的方法调用)。但是,当我尝试在登录操作之后向安全url发送请求时,它返回401代码。我知道,很明显,新请求创建了一个新会话,但是有没有办法执行“记住我”行为而不在每个请求的主体中发送登录信息?以下是我的一些代码:

package com.checkpoint.aimer.security;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;

public class RestSecurityFilter extends AbstractAuthenticationProcessingFilter{

    public RestSecurityFilter(String url, AuthenticationManager m) {
        super(url);
        this.setAuthenticationManager(m);
    }


    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
            HttpServletResponse response) throws AuthenticationException,
            IOException, ServletException {
        HttpSession session = request.getSession();

        Authentication auth = this.getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken("roman", "sawawluha"));
        SecurityContextHolder.getContext().setAuthentication(auth);

        return auth;
    }
}
安全配置:

package com.checkpoint.aimer.security;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public RestSecurityFilter restSecurity() throws Exception {
        RestSecurityFilter filter = new RestSecurityFilter("/auth/login_test", authenticationManagerBean());
        return filter;
    }

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

    @Bean
    public UserDetailsService usr() {
        return new UserSecurityService();
    }

    @Override 
    public void configure(HttpSecurity http) throws Exception{
        http
            .httpBasic().authenticationEntryPoint(new AuthenticationEntryPoint() {

                @Override
                public void commence(HttpServletRequest request, HttpServletResponse response,
                        AuthenticationException arg2) throws IOException, ServletException {
                    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Oops");

                }
            }).and()
            .addFilterBefore(restSecurity(),BasicAuthenticationFilter.class )
            .rememberMe().rememberMeServices(new TokenBasedRememberMeServices("key",usr()) ).and()
            .authorizeRequests()
                .antMatchers("/**").hasRole("USER")
                .antMatchers("/auth/**").anonymous()
                .and()
            .csrf().disable()
            .logout().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception{
        auth
            .userDetailsService(usr());
    }



}

你有什么想法吗

记住我的功能主要是基于cookie实现的。您可以将一些身份验证令牌存储到cookie中。我相信你甚至可以使用会话Cookies来实现这一点

但请记住:

  • 您必须始终使用HTTPS
  • 始终使用cookie属性
  • 始终使用cookie属性

因为cookie随每个请求一起发送到客户端,所以您需要确保它是通过安全通道发送的,并且不可被跨站点攻击访问。

您的意思是-服务器将创建一个
httpOnly
secure
cookie,该cookie将保存访问令牌,然后服务器将其设置为浏览器?然后,此cookie将随每个请求一起发送,这解决了REST中的“记住我”功能,并且此“记住我”将取决于cookie?令牌在服务器上是否过期。您不能依赖客户端使cookie过期。