我正在尝试将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等创建具体的实现?
答案 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>
这看起来很酷,所以我非常愿意看看其他建议。因此,我将这个问题保持开放,不接受这个答案。