最近做项目遇到一个棘手的问题, 项目是用spring security来控制权限的,这个框架有一套他自己的验证,
现在项目的要求是除了去数据库验证之外还要调用OA系统验证用户名和密码,就是在原来的基础上多加一层验证
而且密码不是要加密的,要原文传过去
public UserDetails loadUserByUseraccount(String useraccount);
由于这个方法只能获取用户名,而且根据用户名到数据库查的密码是加密后的,所以不能在这里下手
看了一篇博文说是扩展 loadUserByUseraccount 这个方法的参数
我试了一下,是可行的 但是要 重写很多类 麻烦!就没采用了
博文地址是:http://www.xeclipse.com/?p=1359
其实很简单 只要写一个类继承spring 中的 DaoAuthenticationProvider就好了!
先看custom-secutity.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:s="http://www.springframework.org/schema/security" 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.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<bean id="securityMetadataSource"
class="org.openkoala.koala.auth.ss3adapter.SecurityMetadataSource">
<property name="provider" ref="authDataService"></property>
</bean>
<bean id="userDetailManager" class="org.openkoala.koala.auth.ss3adapter.UserDetailManager">
<property name="provider" ref="authDataService"></property>
</bean>
<bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder"/>
<bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource">
<property name="userPropertyToUse" value="username"></property>
</bean>
<bean id="accessDecisionManager" class="org.openkoala.koala.auth.ss3adapter.AccessDecisionManager"/>
<bean id="loginAuthenticationManager" class="com.csair.efb.web.LoginAuthenticationManager">
<property name="userDetailsService" ref="userDetailManager"></property>
<property name="passwordEncoder" ref="passwordEncoder"></property>
<property name="saltSource" ref="saltSource"></property>
<property name="config" ref="JdbcSecurityConfig"></property>
</bean>
<bean id="securityFilter" class="org.openkoala.koala.auth.ss3adapter.SecurityFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="securityMetadataSource" ref="securityMetadataSource" />
</bean>
<s:authentication-manager alias="authenticationManager">
<s:authentication-provider ref="loginAuthenticationManager" />
</s:authentication-manager>
</beans>
其实就只要看 loginAuthenticationManager 这个bean 以及它要注入的bean, 其他跟原来一样
再看这个类:
package com.csair.efb.web;
import javax.inject.Named;
import org.openkoala.koala.auth.impl.jdbc.JdbcSecurityConfig;
import org.openkoala.koala.auth.impl.jdbc.SecurityManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.authentication.dao.SaltSource;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import com.csair.efb.core.information.TerminalUser;
/**
* 重写DaoAuthenticationProvider的验证方法 可以在这里扩展验证
*
* @ClassName: LoginAuthenticationManager
* @Description: TODO
* @author: wys
* @date: 2013-9-11
*
*/
@Named("loginAuthenticationManager")
public class LoginAuthenticationManager extends DaoAuthenticationProvider {
private JdbcSecurityConfig config;
private static final String SUCCESS = "SUCCESS";
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
Object salt = null;
if (getSaltSource() != null) {
salt = getSaltSource().getSalt(userDetails);
}
if (authentication.getPrincipal() == null
|| "".equals(authentication.getPrincipal())) {
logger.debug("-----用户名不能为空!-----");
throw new BadCredentialsException("-----用户名不能为空!-----");
}
if (authentication.getCredentials() == null
|| "".equals(authentication.getCredentials())) {
logger.debug("-----密码不能为空!-----");
throw new BadCredentialsException("-----密码不能为空!-----");
}
String presentedPassword = authentication.getCredentials().toString();
boolean validResult = !getPasswordEncoder().isPasswordValid(userDetails.getPassword(), presentedPassword, salt);
if (validResult) {
logger.debug("---- 用户名或密码错误!-----");
throw new BadCredentialsException("-----用户名或密码错误!-----");
}
if (!isOAVaild(authentication)) {
logger.debug("-----登陆OA系统失败!-----");
throw new BadCredentialsException("-----登陆OA系统失败!-----");
}
}
/**
* 调用OA系统
*
* @param userDetails
* @param authentication
* @return
*/
public boolean isOAVaild(UsernamePasswordAuthenticationToken authentication) {
boolean result = false;
/**
* 如果是管理员则不经过OA验证
*/
boolean flag = config.getUseAdmain().equals("true")
&& config.getAdminAccount().equals(
(String) authentication.getPrincipal());
if (flag) {
result = true;
} else {
String loginResult = TerminalUser.newInstance(
(String) authentication.getPrincipal(),
(String) authentication.getCredentials()).login();
if (SUCCESS.equals(loginResult)) {
result = true;
}
}
return result;
}
public JdbcSecurityConfig getConfig() {
return config;
}
public void setConfig(JdbcSecurityConfig config) {
this.config = config;
}
}
类中authentication就能访问到原始密码和用户名,随便你怎么扩展都行!
到此,搞了几天问题终于搞好了!希望遇到此问题的人别走弯路!