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