我正在使用spring mvc框架和java开发一个Web应用程序。我在应用程序中使用了活动目录用户身份验证。
现在我想从sql数据库为这些用户分配角色。因此,整个身份验证过程将通过从两个来源获取信息来完成:[用户ID和来自活动目录的密码&来自sql数据库的用户角色]。
我在互联网上搜索了任何教程/样本,但我无法获得任何有用的东西。因此,对此问题的任何帮助都将不胜感激。
这是我的spring安全文件的当前代码,
<bean id="adAuthenticationProvider"
class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="abbl.org"/>
<constructor-arg value="LDAP://abbl.org"/>
<property name="convertSubErrorCodesToExceptions" value="true"/>
<property name="useAuthenticationRequestCredentials" value="true"/>
</bean>
<bean id="customAuthenticationProvider"
class="org.abbl.exhbp.templates.CustomAuthorityProvider">
<constructor-arg ref="adAuthenticationProvider"/>
</bean>
<security:authentication-manager>
<security:authentication-provider ref="customAuthenticationProvider"/>
</security:authentication-manager>
我在AuthenticationProvider类中的身份验证函数,
public Authentication authenticate(Authentication authentication) {
final Authentication a = delegate.authenticate(authentication);
// Load additional authorities and create an Authentication object
final List<GrantedAuthority> authorities = getGrantedAuthorities(a.getName());
return new AbstractAuthenticationToken(authorities) {
@Override
public Object getCredentials() {
//return null; //To change body of implemented methods use File | Settings | File Templates.
throw new UnsupportedOperationException();
}
@Override
public Object getPrincipal() {
//return null; //To change body of implemented methods use File | Settings | File Templates.
return a.getPrincipal();
}
};
}
登录后,我收到此异常,
java.lang.UnsupportedOperationException
org.abbl.exhbp.templates.CustomAuthorityProvider$1.getCredentials(CustomAuthorityProvider.java:41)
org.springframework.security.authentication.AbstractAuthenticationToken.eraseCredentials(AbstractAuthenticationToken.java:108)
org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:186)
org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:195)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
为了达到我上面提到的目的,我需要做哪些修改或实施?
答案 0 :(得分:0)
最后,我通过使用UsernamePasswordAuthenticationToken而不是AbstractAuthenticationToken实现了我的目标。解决方案如下,
1)spring-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<security:http auto-config="true" use-expressions="true">
<security:anonymous enabled="false"/>
<security:form-login login-page="/login" default-target-url="/home"
login-processing-url="/j_spring_security_check"
authentication-failure-url="/loginfailed"/>
<security:logout logout-success-url="/logout"/>
</security:http>
<bean id="adAuthenticationProvider"
class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="DOMAIN"/>
<constructor-arg value="URL"/>
<property name="convertSubErrorCodesToExceptions" value="true"/>
<property name="useAuthenticationRequestCredentials" value="true"/>
</bean>
<bean id="customAuthenticationProvider"
class="org.abbl.exhbp.templates.CustomAuthorityProvider">
<constructor-arg ref="adAuthenticationProvider"/>
</bean>
<security:authentication-manager>
<security:authentication-provider ref="customAuthenticationProvider"/>
</security:authentication-manager>
2)CustomAuthorityProvider.class
public class CustomAuthorityProvider implements AuthenticationProvider {
private AuthenticationProvider delegate;
public CustomAuthorityProvider(AuthenticationProvider delegate) {
this.delegate = delegate;
}
public Authentication authenticate(Authentication authentication) {
final Authentication a = delegate.authenticate(authentication);
// Load additional authorities and create an Authentication object
final List<GrantedAuthority> authorities = getGrantedAuthorities(a.getName());
return new UsernamePasswordAuthenticationToken(a.getPrincipal(),a.getCredentials(),authorities);
}
@Override
public boolean supports(Class<?> authentication) {
return delegate.supports(authentication);
}
List<GrantedAuthority> getGrantedAuthorities(String username) {
JdbcTemplateDataSource ds = new JdbcTemplateDataSource();
List<GrantedAuthority> roles = ds.getJdbcTemplate().query("select r.Role from Users u join UserRole ur on u.UserId = "
+ "ur.UserId join Roles r on r.RoleId = ur.RoleId where Username = ?",
new String[]{username},
new RowMapper<GrantedAuthority>() {
public GrantedAuthority mapRow(ResultSet rs, int rowNum) throws SQLException {
return new SimpleGrantedAuthority(rs.getString(1));
}
});
return roles;
}
}