Spring Session 和 Spring Security
Posted
技术标签:
【中文标题】Spring Session 和 Spring Security【英文标题】:Spring Session and Spring Security 【发布时间】:2015-06-11 08:33:12 【问题描述】:我对以下方面有疑问:spring-session 和 spring-security。
春季会议
我有一个应用程序通过示例示例中提供的基本内存中身份验证受 Spring Security 保护。
我看到 spring 正在创建会话 ID,即使身份验证不成功,这意味着即使我不提供基本身份验证凭据详细信息,我也会在我的响应标头以及 Redis DB 中看到x-auth-token
。
我们如何避免为身份验证失败创建会话?
Spring 安全
想使用 spring security 来保护资源,假设 spring session 只为受保护的资源创建 session。
假设登录 API(/signin - HTTP Post)根据第三方 REST API 验证(用户名和密码)凭据。
外部 API 验证凭据后,如何在成功验证时更新 spring 安全上下文?
需要验证通过x-auth-token
访问其他受保护资源的权限,并根据信息提供对受保护资源的访问权限。
在这种情况下我们需要 Spring Security 还是应该使用基本过滤器和 Spring 会话?有什么推荐的?
【问题讨论】:
【参考方案1】:通常最好将您的问题分解为多个 *** 问题,因为您更有可能找到知道单个问题答案的人而不是两者。
我们如何避免为身份验证失败创建会话?
默认情况下,Spring Security 会将最后一个未经身份验证的请求保存到会话中,以便在您进行身份验证后它可以自动再次发出请求。例如,在浏览器中,如果您请求 example.com/a/b/c 并且未通过身份验证,它将将 example.com/a/b/c 保存到 HttpSession,然后让用户进行身份验证。在您通过身份验证后,它会自动为您提供 example.com/a/b/c 的结果。这提供了良好的用户体验,因此您的用户无需再次键入 URL。
在 REST 服务的情况下,这不是必需的,因为客户端会记住需要重新请求哪个 URL。您可以通过修改配置以使用 NullRequestCache 来阻止保存,如下所示:
protected void configure(HttpSecurity http) throws Exception
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.requestCache()
.requestCache(new NullRequestCache())
.and()
.httpBasic();
您可以通过提供自己的 AuthenticationProvider 来提供自定义身份验证。例如:
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
public class RestAuthenticationProvider implements AuthenticationProvider
public Authentication authenticate(Authentication authentication)
throws AuthenticationException
UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;
String username = token.getName();
String password = (String) token.getCredentials();
// validate making REST call
boolean success = true;
// likely your REST call will return the roles for the user
String[] roles = new String[] "ROLE_USER" ;
if(!success)
throw new BadCredentialsException("Bad credentials");
return new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(roles));
public boolean supports(Class<?> authentication)
return (UsernamePasswordAuthenticationToken.class
.isAssignableFrom(authentication));
然后您可以使用以下方式配置您的 RestAuthenticationProvider:
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter
...
@Bean
public RestAuthenticationProvider restAuthenticationProvider()
return new RestAuthenticationProvider();
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth, AuthenticationProvider provider) throws Exception
auth
.authenticationProvider(provider);
【讨论】:
谢谢你 rob,我肯定会尝试将我的问题分成多个帖子。我会尝试你的答案,并会回复你。再次非常感谢您,对于延迟回复感到抱歉 configure方法放哪里了?【参考方案2】:即使身份验证失败,会话 ID 也会存储在 Redis 中。
Rob 设置 NullRequestCache 的答案对我不起作用。也就是说,即使将请求缓存设置为 NullRequestCache,也有 redis 条目。为了让它工作,我不得不使用身份验证失败处理程序。
http.formLogin().failureHandler(authenticationFailureHandler()).permitAll();
private AuthenticationFailureHandler authenticationFailureHandler()
return new AuthenticationFailureHandler();
public class AuthenticationFailureHandler
extends SimpleUrlAuthenticationFailureHandler
请注意,失败处理程序除了显式扩展默认处理程序之外什么都不做。如果失败,它会返回 401。如果您正在执行重定向,您可以在处理程序中轻松配置它。
【讨论】:
以上是关于Spring Session 和 Spring Security的主要内容,如果未能解决你的问题,请参考以下文章
帅气的 Spring Session 功能,基于 Redis 实现分布式会话,还可以整合 Spring Security!
spring-session-data-redis反序列化问题