2015-04-06 154 views
7

我对以下几个方面有疑问:spring-session和spring-security。Spring Session和Spring Security

春季会议

我必须通过基本内存验证与春季安全保护的应用程序的例子示例中提供。

我看到spring正在创建会话ID,即使身份验证不成功,也就是说,即使我没有提供基本身份验证凭据详细信息,我在我的响应头中也看到了x-auth-token。 我们如何避免为验证失败创建会话?

春季安全

需要使用Spring的安全保护资源假设春季会议只针对受保护的资源创建会话。

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

一旦外部API验证凭据,如何更新成功验证的弹簧安全上下文?

需要验证对x-auth-token的其他安全资源的访问权限,并且应该提供基于访问安全资源的信息。

我们是否需要在这种情况下拥有Spring Security?还是我应该使用基本的过滤器和弹簧会话?建议什么?

回答

11

通常最好将您的问题分解为多个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); 
    } 
} 
+0

谢谢抢劫,当然我会尝试将我的问题分解为多个帖子。我会尝试你的答案,并会回复你。再次非常感谢你,并对延迟响应感到抱歉 –

+0

你在哪里放置配置方法? – snowe

0

会话ID越来越存储在Redis的,即使验证失败。

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

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

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

public class AuthenticationFailureHandler 
    extends SimpleUrlAuthenticationFailureHandler { 
} 

请注意,失败处理程序只会显式扩展默认处理程序。如果失败,它将返回401。如果您正在执行重定向,则可以轻松地在处理程序中配置它。