春季会议和春季安全

时间:2015-04-06 21:16:18

标签: spring-security spring-session

我对以下方面有疑问:春季会议和春季安全。

春季会议

我有一个受Spring Security保护的应用程序,通过示例示例中提供的基本内存中身份验证。

我看到spring正在创建会话ID,即使身份验证不成功,这意味着即使我不提供基本身份验证凭据详细信息,我也会在Redis数据库中看到x-auth-token。 我们如何避免为身份验证失败创建会话?

Spring Security

假设spring会话仅为受保护资源创建会话,则希望使用spring security来保护资源。

假设Signin API(/ signin - HTTP Post)针对第三方REST API验证(用户名和密码)凭据。

外部API验证凭据后,如何在成功验证时更新spring安全上下文?

需要验证对x-auth-token的其他安全资源的访问权限,并且应根据信息访问受保护资源。

我是否需要在这种情况下使用Spring Security或者我应该使用基本的过滤器和弹簧会话?推荐什么?

2 个答案:

答案 0 :(得分:14)

通常最好将您的问题分解为多个StackOverflow问题,因为您更有可能找到知道单个问题答案的人而不是两者。

  

我们如何避免为身份验证失败创建会话?

默认情况下,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);
    }
}

答案 1 :(得分:2)

  

即使身份验证失败,会话ID也会存储在Redis中。

Rob设置NullRequestCache的答案对我没有用。也就是说,即使在将请求缓存设置为NullRequestCache之后,也存在redis条目。为了使它工作,我不得不使用身份验证失败处理程序。

http.formLogin().failureHandler(authenticationFailureHandler()).permitAll();

private AuthenticationFailureHandler authenticationFailureHandler() {
    return new AuthenticationFailureHandler();
}

public class AuthenticationFailureHandler 
    extends SimpleUrlAuthenticationFailureHandler {
}

请注意,失败处理程序除了显式扩展默认处理程序外什么都不做。如果发生故障,它将返回401。如果您正在进行重定向,则可以在处理程序中轻松配置它。

相关问题