不使用角色进行身份验证的Spring安全授权

时间:2013-12-02 10:39:43

标签: java spring-security

我正在尝试将spring security的授权元素实现到我们的应用程序中。我们有一个外部身份验证过程,只是想使用spring security来阻止没有特定角色的人访问某些URL。我们希望将用户角色作为http请求中的标头传递,并确定用户是否可以在不知道其名称或密码的情况下查看该网址。

看了很多文档之后,我还没有看到有人这样做的例子,但我相信它的方法是扩展AbstractPreAuthenticatedProcessingFilter并从请求中获取角色,如下所示:

public class RequestHeaderPreAuthenticatedProcessingFilterImpl extends
    AbstractPreAuthenticatedProcessingFilter {

   private final String PRINCIPAL_REQUEST_HEADER = "user-role";

   private final boolean EXCEPTION_IF_HEADER_MISSING = true;

   @Override
   protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
       String principal = request.getHeader(PRINCIPAL_REQUEST_HEADER);
       if (principal == null && EXCEPTION_IF_HEADER_MISSING) {
           throw new PreAuthenticatedCredentialsNotFoundException(PRINCIPAL_REQUEST_HEADER
                + " header not found in request.");
       }
       return principal;

   }

   @Override
   protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
       return "N/A";
   }

}

我的问题是:
1)这是解决问题的正确方法吗? 2)作为委托人返回什么是正确的?它是角色,还是包含虚拟用户信息的UserDetails对象?
3)我能将其插入预定义的Spring对象中,还是必须为Authentication Manager,provider等创建具体的实现?

1 个答案:

答案 0 :(得分:1)

我解决这个问题的方法是创建AuthenticationProvider和AbstractPreAuthenticatedProcessingFilter的实现。这允许我从请求中获取相关标头,将主体设置为角色列表,并自己进行身份验证。

我的AbstractPreAuthenticatedProcessingFilter:

的实现
public class RequestHeaderPreAuthenticatedProcessingFilterImpl extends
    AbstractPreAuthenticatedProcessingFilter {

private final String PRINCIPAL_REQUEST_HEADER = "user-role";

private boolean exceptionIfHeaderMissing = true;

    @Override
    protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
        String principal = request.getHeader(PRINCIPAL_REQUEST_HEADER);
        if (principal == null && exceptionIfHeaderMissing) {
            throw new PreAuthenticatedCredentialsNotFoundException(PRINCIPAL_REQUEST_HEADER
                + " header not found in request.");
        }
        GrantedAuthority[] grantedAuthority = new GrantedAuthority[1];
        grantedAuthority[0] = new SimpleGrantedAuthority(principal);
        Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        authorities.add(grantedAuthority[0]);
        return authorities;
    }

    @Override
    protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
         return "N/A";
    }

    public void setExceptionIfHeaderMissing(boolean exceptionIfHeaderMissing) {
        this.exceptionIfHeaderMissing = exceptionIfHeaderMissing;
    }

}

我的AuthenticationProvider实现:

public class AuthenticationProviderImpl implements AuthenticationProvider {

    @SuppressWarnings("unchecked")
    @Override
    public Authentication authenticate(Authentication authentication)
        throws AuthenticationException
    {
        Collection<? extends GrantedAuthority> authorities =
            (Collection<GrantedAuthority>)authentication.getPrincipal();
        PreAuthenticatedAuthenticationToken auth =
            new PreAuthenticatedAuthenticationToken(null, null, authorities);
        return auth;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return true;
    }

}

我的Java应用程序配置:

@Configuration
@ImportResource("classpath:spring-security.xml")
public class ApplicationConfiguration {

    @Bean
    public AbstractPreAuthenticatedProcessingFilter roleFilter() {
        RequestHeaderPreAuthenticatedProcessingFilterImpl filter =
            new RequestHeaderPreAuthenticatedProcessingFilterImpl();
        filter.setAuthenticationManager(authenticationManager());
        filter.setCheckForPrincipalChanges(true);
        filter.setExceptionIfHeaderMissing(false);
        return filter;
    }

    @Bean
    public AuthenticationProvider authenticationProvider() {
        return new AuthenticationProviderImpl();
    }

    @Bean(name = "authenticationManager")
    public AuthenticationManager authenticationManager() {
        List<AuthenticationProvider> authProviderList = new     ArrayList<AuthenticationProvider>();
        authProviderList.add(authenticationProvider());
        AuthenticationManager authenticationManager = new ProviderManager(authProviderList);
        return authenticationManager;
    }
}

我的spring-security.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.1.xsd">

    <http use-expressions="true" auto-config="true" authentication-manager-ref="authenticationManager">
        <custom-filter position="PRE_AUTH_FILTER" ref="roleFilter" />
    <intercept-url pattern="/**" access="hasRole(ROLE_ADMIN)"/>
    </http>

</beans:beans>

这看起来很酷,所以我非常愿意看看其他建议。因此,我将这个问题保持开放,不接受这个答案。