最近做项目遇到一个棘手的问题, 项目是用spring security来控制权限的,这个框架有一套他自己的验证,

现在项目的要求是除了去数据库验证之外还要调用OA系统验证用户名和密码,就是在原来的基础上多加一层验证

而且密码不是要加密的,要原文传过去

public UserDetails loadUserByUseraccount(String useraccount);

由于这个方法只能获取用户名,而且根据用户名到数据库查的密码是加密后的,所以不能在这里下手

看了一篇博文说是扩展 loadUserByUseraccount 这个方法的参数

我试了一下,是可行的 但是要 重写很多类 麻烦!就没采用了

其实很简单 只要写一个类继承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就能访问到原始密码和用户名,随便你怎么扩展都行!

到此,搞了几天问题终于搞好了!希望遇到此问题的人别走弯路!