Spring Session 和 Spring 安全
Spring Session and Spring Security
我对以下方面有疑问:spring-session 和 spring-security。
Spring Session
我有一个应用程序受到 Spring 安全保护,通过示例中提供的基本 in-memory 身份验证。
我看到 spring 正在创建 session id 即使身份验证不成功,这意味着我在我的响应 header 中看到 x-auth-token
以及 Redis DB 即使我不提供基本的身份验证凭据详细信息。
我们如何避免为身份验证失败创建 sessions?
Spring 安全性
想要使用 spring 安全性来保护资源,假设 spring session 仅为受保护的资源创建 session。
假设登录 API (/signin - HTTP Post) 根据 third-party REST API 验证(用户名和密码)凭据。
一旦外部 API 验证凭据,如何在成功验证时更新 spring 安全上下文?
需要验证对具有 x-auth-token
的其他受保护资源的访问权限,并且应根据信息提供对受保护资源的访问权限。
在这种情况下我们需要 Spring 安全性还是我应该使用基本过滤器和 spring session?推荐什么?
通常最好将您的问题分解为多个 Whosebug 问题,因为您更有可能找到知道单个问题答案的人,而不是两者都知道的人。
How do we avoid creating sessions for authentication failures ?
默认情况下Spring安全会将最后一个未经身份验证的请求保存到会话中,以便在您进行身份验证后它可以自动再次发出请求。例如,在浏览器中,如果您请求 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);
}
}
Session IDs are getting stored in Redis even when authentication fails.
Rob 关于设置 NullRequestCache 的回答对我不起作用。也就是设置request cache为NullRequestCache后,redis entry还是有的。为了让它工作,我必须使用身份验证失败处理程序。
http.formLogin().failureHandler(authenticationFailureHandler()).permitAll();
private AuthenticationFailureHandler authenticationFailureHandler() {
return new AuthenticationFailureHandler();
}
public class AuthenticationFailureHandler
extends SimpleUrlAuthenticationFailureHandler {
}
请注意,失败处理程序除了显式扩展默认处理程序外什么都不做。它 returns 一个 401 以防失败。如果你正在做重定向,你可以很容易地在处理程序中配置它。
我对以下方面有疑问:spring-session 和 spring-security。
Spring Session
我有一个应用程序受到 Spring 安全保护,通过示例中提供的基本 in-memory 身份验证。
我看到 spring 正在创建 session id 即使身份验证不成功,这意味着我在我的响应 header 中看到 x-auth-token
以及 Redis DB 即使我不提供基本的身份验证凭据详细信息。
我们如何避免为身份验证失败创建 sessions?
Spring 安全性
想要使用 spring 安全性来保护资源,假设 spring session 仅为受保护的资源创建 session。
假设登录 API (/signin - HTTP Post) 根据 third-party REST API 验证(用户名和密码)凭据。
一旦外部 API 验证凭据,如何在成功验证时更新 spring 安全上下文?
需要验证对具有 x-auth-token
的其他受保护资源的访问权限,并且应根据信息提供对受保护资源的访问权限。
在这种情况下我们需要 Spring 安全性还是我应该使用基本过滤器和 spring session?推荐什么?
通常最好将您的问题分解为多个 Whosebug 问题,因为您更有可能找到知道单个问题答案的人,而不是两者都知道的人。
How do we avoid creating sessions for authentication failures ?
默认情况下Spring安全会将最后一个未经身份验证的请求保存到会话中,以便在您进行身份验证后它可以自动再次发出请求。例如,在浏览器中,如果您请求 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);
}
}
Session IDs are getting stored in Redis even when authentication fails.
Rob 关于设置 NullRequestCache 的回答对我不起作用。也就是设置request cache为NullRequestCache后,redis entry还是有的。为了让它工作,我必须使用身份验证失败处理程序。
http.formLogin().failureHandler(authenticationFailureHandler()).permitAll();
private AuthenticationFailureHandler authenticationFailureHandler() {
return new AuthenticationFailureHandler();
}
public class AuthenticationFailureHandler
extends SimpleUrlAuthenticationFailureHandler {
}
请注意,失败处理程序除了显式扩展默认处理程序外什么都不做。它 returns 一个 401 以防失败。如果你正在做重定向,你可以很容易地在处理程序中配置它。