欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

cas4.0 服务端添加自定义认证器,单点登录认证数据库用户和LDAP用户

程序员文章站 2024-03-24 22:09:10
...

这段时间做CAS4.0的单点登录,整合LDAP的时候查了网上资料,最后还是怎么整都有问题,就换了这种方式,自己写个认证器去认证数据库的用户和LDAP的用户。
总结一下给自己看,共3步。
1、添加自定义认证器,主要是认证的逻辑。
2、添加解析器,用于自定义返回参数。
3、配置deployerConfigContext.xml。

1 添加自定义认证器

package com.msxf.sso.authentication;
 
import java.security.GeneralSecurityException;
import java.security.MessageDigest;

import javax.annotation.Resource;
import javax.security.auth.login.FailedLoginException;
 
import org.jasig.cas.authentication.HandlerResult;
import org.jasig.cas.authentication.PreventedException;
import org.jasig.cas.authentication.UsernamePasswordCredential;
import org.jasig.cas.authentication.handler.MyPasswordEncoder;
import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.jasig.cas.authentication.principal.SimplePrincipal;
import org.jasig.cas.mylogin.util.PropertyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
/**
 * 自定义的用户登录认证类
 */
@Component(value="primaryAuthenticationHandler")
public class MyUserAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler {
	//@Resource
/*	@Autowired
	private MyUserDoaJdbc myUserDoaJdbc;*/	
	/**
	 * 认证用户名和密码是否正确
	 * @see UsernamePasswordCredential参数包含了前台页面输入的用户信息
	 */
	@Override
	protected HandlerResult authenticateUsernamePasswordInternal(UsernamePasswordCredential transformedCredential) throws GeneralSecurityException, PreventedException {
		String username = transformedCredential.getUsername();
		String password = transformedCredential.getPassword();
	
		MyUserDoaJdbc myUserDoaJdbc = new MyUserDoaJdbc();
		try {
			PropertyUtil propertyUtil = new PropertyUtil();
			if( myUserDoaJdbc.verifyAccount(username,MD5(password.toLowerCase()))  	 \\数据库验证逻辑
					|| myUserDoaJdbc.verifyLDAPAccount(username, password)) ){		\\LDAP验证逻辑
				 return createHandlerResult(transformedCredential, new SimplePrincipal(username), null);   \\返回数据
			}else{
				throw new FailedLoginException();
			}
		} catch (Exception e) {
			System.out.println(e);
		}
		return  null;
	}

/*	public MyUserDoaJdbc getMyUserDoaJdbc() {
		return myUserDoaJdbc;
	}


	public void setMyUserDoaJdbc(MyUserDoaJdbc myUserDoaJdbc) {
		this.myUserDoaJdbc = myUserDoaJdbc;
	}*/	
}

认证的逻辑

package com.msxf.sso.authentication;

import java.sql.ResultSet;
import javax.annotation.Resource;
import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import org.apache.commons.codec.digest.DigestUtils;
import org.jasig.cas.mylogin.util.JdbcUtils_C3P0;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.transaction.annotation.Transactional;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class MyUserDoaJdbc{
	private  LdapContext ctx = null;
	private  Control[] connCtls = null;

	/**** 定义LDAP的基本连接信息 ******/
	// LDAP的连接地址(ldap://ip:port/)port默认为389
	private static String URL = "ldap://192.168.0.1:389/";
	// LDAP的根DN
	private static String BASEDN = "dc=authldap,dc=edu,dc=cn";
	// LDAP的连接账号(身份认证管理平台添加的应用账号,应用账号格式:uid=?,ou=?,dc=????)
	private static String PRINCIPAL = "uid=hbsi_ldap,ou=Manager,dc=authldap,dc=edu,dc=cn";
	// LDAP的连接账号的密码(身份认证管理平台添加的应用账号的密码)
	private static String PASSWORD = "123456";
	
	private JdbcTemplate jdbcTemplate;
	
	public MyUserDoaJdbc() {
		super();
		jdbcTemplate = new JdbcTemplate();
		jdbcTemplate.setDataSource(JdbcUtils_C3P0.getComboPooledDataSource());\\配置数据库连接
	}

	public JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}

	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	/**
	 * 验证数据库用户名和密码是否正确
	 */
	public boolean verifyAccount(String username, String password){
		String sql = "SELECT password FROM user_all_views WHERE username=?";
		try{
		    String dbPassword = jdbcTemplate.queryForObject(sql, String.class, username);       
		    if (dbPassword.equals(password)) {
		    	System.out.println("verifyAccount : true");
		         return true;
		    }
		    System.out.println("verifyAccount : false");
		         return false;
		}catch(EmptyResultDataAccessException e){
			System.out.println(e);
			return false;
		}catch(Exception e){
			System.out.println(e);
			return false;
		}
	}
	
	/**
	 * 验证LDAP用户名和密码是否正确
	 */
	@Transactional
	public boolean verifyLDAPAccount(String username, String password){
		boolean valide = false;
	    if (password == null || password == "")
			return false;
	    if (ctx == null) {
	       getCtx();//连接LDAP
	   }
	    Map userMap = getUserDN(username);
	    String userDN = (String) userMap.get("userDN");
	    Map resultDNMap = (Map) userMap.get("resultDN");
	    if ("".equals(userDN) || userDN == null) {
	       return false;
	   }
	    try {
	       ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN);
	       ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
	       ctx.reconnect(connCtls);
	       valide = true;
	   } catch (AuthenticationException e) {
	       System.out.println(userDN + " 未验证1");
	       valide = false;
	   } catch (NamingException e) {
	       System.out.println(userDN + " 未验证2");
	       valide = false;
	   }
	  
	    return valide;
	}
	
	public  void getCtx() {
		   if (ctx != null) {
		       return;
		   }
		   Hashtable<String, String> env = new Hashtable<String, String>();
		   env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
		   env.put(Context.PROVIDER_URL, URL + BASEDN);
		   env.put(Context.SECURITY_AUTHENTICATION, "simple");
		   env.put(Context.SECURITY_PRINCIPAL, PRINCIPAL);
		   env.put(Context.SECURITY_CREDENTIALS, PASSWORD);
		   System.out.println(env.toString());
		   try {
		       // 链接ldap
		       ctx = new InitialLdapContext(env, connCtls);
		       System.out.println("链接ldap成功");
		   } catch (javax.naming.AuthenticationException e) {
		       System.out.println("验证失败: " + e.toString());
		   } catch (Exception e) {
			   closeCtx();
		       System.out.println("验证发生异常: " + e.toString());
		   }
	    }

	    public  void closeCtx() {
		   try {
		       if (ctx != null){
		       		ctx.close(); 
		       		ctx = null;
		    		connCtls = null;
		       }
		   } catch (NamingException ex) {
			   System.out.println(ex);
		   }
		    }

	    public Map getUserDN(String uid) {
	    	System.out.println("uid:   "+uid);
		   String userDN = "";
		   Map resultDN = new HashMap();
		   Map<String, Object> resultMap = new HashMap();
		   try {
		       SearchControls constraints = new SearchControls();
		       constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
		       NamingEnumeration<?> en = ctx.search("", "uid=" + uid, constraints);
		       if (en == null) {
		    	   System.out.println("getUserDN : Have no NamingEnumeration.");
		       }
		       if (!en.hasMoreElements()) {
		    	   System.out.println("getUserDN : Have no element.");
		       }
		       while (en != null && en.hasMoreElements()) {
			      Object obj = en.nextElement();
			      System.out.println("getUserDN:    "+obj.toString());
			      if (obj instanceof SearchResult) {
			          SearchResult si = (SearchResult) obj;
			          userDN += si.getName();
			          userDN += "," + BASEDN;
			          resultDN.put("uid", si.getAttributes().get("uid"));
			          resultDN.put("cn", si.getAttributes().get("cn"));
			          resultDN.put("securityEmail", si.getAttributes().get("securityEmail"));
			          resultDN.put("telephoneNumber", si.getAttributes().get("telephoneNumber"));
			          resultMap.put("userDN", userDN);
			          resultMap.put("resultDN", resultDN);
			      } else {
			          System.out.println(obj);
			      }
		       }
		   } catch (Exception e) {
			   closeCtx();
		       System.out.println("查询时发生异常:" + e);
		   }
		   return resultMap;
	    }
	 
	
	    
	/**
	 * 根据用户名获取用户信息
	 */
	public UserView getByUsername(String username){
		String sql = "SELECT * FROM user_all_views WHERE username=?";
		try{
			UserView user = (UserView)jdbcTemplate.queryForObject(sql, new Object[]{username}, new UserViewRowMapper());
			return user;
		}catch(EmptyResultDataAccessException e){
			System.out.println("that  :"+e);
			return new UserView();
		}catch(Exception e){
			System.out.println("this:  "+e);
			return new UserView();
		}
	}
	
	/**
	 * 获取用户权限信息
	 * @param username
	 * @return
	 */
	public Permission getPermissionInfo(int roleId,String permissionType){

		 String sql = "SELECT p.name as permission_name,p.guard_name as permission_guard_name,r.name as role_name,r.guard_name as role_guard_name FROM roles r,permissions p,role_has_permissions rh WHERE r.id = rh.role_id AND p.id = rh.permission_id AND r.id = ? AND p.name = ?";
		 try{
			 Permission psermission = (Permission)jdbcTemplate.queryForObject(sql, new Object[]{roleId,permissionType}, new PermissionRowMapper());
			 return psermission;
		}catch(EmptyResultDataAccessException e){
			return new Permission();
		}
	}
	
	/**
	 * 查询权限信息
	 * @author Administrator
	 *
	 */
	class PermissionRowMapper implements RowMapper<Permission> {
		@Override
		public Permission mapRow(ResultSet rs, int index) throws SQLException {

			Permission permission = new Permission();
			permission.setPermission_name(rs.getString("permission_name"));
			permission.setPermission_guard_name("permission_guard_name");
			permission.setRole_name("role_name");
			permission.setRole_guard_name("role_guard_name");

			return permission;
		}
	}
	
	class UserViewRowMapper implements RowMapper<UserView> {
		@Override
		public UserView mapRow(ResultSet rs, int index) throws SQLException {
			
			UserView user = new UserView();
			user.setUsername(rs.getString("username"));
			user.setPassword(rs.getString("password"));
			user.setNickname(rs.getString("nickname"));
			user.setId(rs.getInt("id"));
			user.setSex(rs.getInt("sex"));
			user.setPhone(rs.getString("phone"));
			user.setEmail(rs.getString("email"));
			user.setAvatar(rs.getString("avatar"));
			user.setType(Integer.parseInt(rs.getString("type")));
			user.setNumber(rs.getString("number"));
			user.setGroup_id(Integer.parseInt(rs.getString("group_id")));
			
			return user;
		}
	}
	
	class TeacherRowMapper implements RowMapper<Teacher> {
		@Override
		public Teacher mapRow(ResultSet rs, int index) throws SQLException {
			Teacher user = new Teacher();
			user.setId(rs.getInt("id"));
			user.setTeach_basic_id(rs.getString("teach_basic_id"));
			user.setWorker_number(rs.getString("worker_number"));
			return user;
		}
	}
		
		class StudentRowMapper implements RowMapper<Student> {
			@Override
			public Student mapRow(ResultSet rs, int index) throws SQLException {
				Student user = new Student();
				user.setStudent_basic_id(rs.getString("student_basic_id"));
				user.setStudent_number(rs.getString("student_number"));
				user.setId(rs.getInt("id"));
				return user;
			}
		}
	
}

数据库连接

package org.jasig.cas.mylogin.util;

import java.sql.ResultSet;
import java.sql.SQLException;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;

public class JdbcUtils_C3P0 {

	private static ComboPooledDataSource ds = null;
	     //在静态代码块中创建数据库连接池
	     static{
	         try{
	             //通过代码创建C3P0数据库连接池
	             ds = new ComboPooledDataSource();
	             ds.setDriverClass("com.mysql.jdbc.Driver");
	             ds.setJdbcUrl("jdbc:mysql://192.168.0.147:3306/mysql?useUnicode=true&amp;characterEncoding=utf8&amp;zeroDateTimeBehavior=convertToNull");
	             ds.setUser("root");
	             ds.setPassword("root");
	         }catch (Exception e) {
	             throw new ExceptionInInitializerError(e);
	         }
	     }
	     
	     /**
	     * @Method: getConnection
	     * @Description: 从数据源中获取数据库连接
	     * @return Connection
	     * @throws SQLException
	     */ 
	     public static Connection getConnection() throws SQLException{
	         //从数据源中获取数据库连接
	         return (Connection) ds.getConnection();
	     }
	     
	     /**
	     * @Method: getConnection
	     * @Description: 从数据源中获取数据库连接
	     * @return Connection
	     * @throws SQLException
	     */ 
	     public static ComboPooledDataSource getComboPooledDataSource(){
	         //从数据源中获取数据库连接
	         return ds;
	     }
	     
	     /**
	     * @param conn
	     * @param st
	     * @param rs
	     */ 
	     public static void release(Connection conn,Statement st,ResultSet rs){
	         if(rs!=null){
	             try{
	                 //关闭存储查询结果的ResultSet对象
	                 rs.close();
	             }catch (Exception e) {
	                 e.printStackTrace();
	             }
	             rs = null;
	         }
	         if(st!=null){
	             try{
	                 //关闭负责执行SQL命令的Statement对象
	                 st.close();
	             }catch (Exception e) {
	                 e.printStackTrace();
	             }
	         }
	         
	         if(conn!=null){
	             try{
	                 //将Connection连接对象还给数据库连接池
	                 conn.close();
	             }catch (Exception e) {
	                e.printStackTrace();
	             }
	         }
	     }
}

2 解析器

package com.msxf.sso.authentication;
 
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jasig.services.persondir.IPersonAttributes;
import org.jasig.services.persondir.support.AttributeNamedPersonImpl;
import org.jasig.services.persondir.support.StubPersonAttributeDao;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

import com.entity.Permission;
 
 
/**
 * 自定义的返回给客户端相关信息
 */
@Component(value="attributeRepositoryer")
public class MyUserStubPersonAttributeDao extends StubPersonAttributeDao {

	MyUserDoaJdbc myuserDaoJdbc = new MyUserDoaJdbc();
	private static final String SQL_USER_GET = "SELECT * FROM user_all_views WHERE username=?";
	
	@Override
	public IPersonAttributes getPerson(String uid) {
		  Map<String, List<Object>> attributes = new HashMap<String, List<Object>>();
		try {	
			  final Map values = myuserDaoJdbc.getJdbcTemplate().queryForMap(SQL_USER_GET,uid);
			  attributes.put("id",Collections.singletonList((Object)values.get("id")));
			  attributes.put("username",Collections.singletonList((Object)uid));
			  attributes.put("password",Collections.singletonList((Object) values.get("password")));
			  attributes.put("nickname",Collections.singletonList((Object) values.get("nickname")));
			  attributes.put("sex",Collections.singletonList((Object) values.get("sex")));
			  attributes.put("phone",Collections.singletonList((Object) values.get("phone")));
			  attributes.put("updated_at",Collections.singletonList((Object) values.get("updated_at")));
			  attributes.put("type",Collections.singletonList((Object) values.get("type")));
			  attributes.put("group_id",Collections.singletonList((Object) values.get("group_id")));
			
			  boolean permissionIsExist = permissionIsExist(Integer.parseInt(attributes.get("group_id").get(0).toString()), "control_center");
			  String permissions = "true";
			  String permission = "false";
			  List li = new ArrayList();
			  if(permissionIsExist){
				  li.add(permissions);
					attributes.put("permission",li);
				}else{
					li.add(permission);
					attributes.put("permission",li);
				}
			  
			  System.out.println("attributes:   "+attributes.toString());
			  return new AttributeNamedPersonImpl(attributes);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return new AttributeNamedPersonImpl(attributes);
	}

	public MyUserDoaJdbc getMyuserDaoJdbc() {
		return myuserDaoJdbc;
	}

	public void setMyuserDaoJdbc(MyUserDoaJdbc myuserDaoJdbc) {
		this.myuserDaoJdbc = myuserDaoJdbc;
	}
	
	/**
	 * 判断用户权限是否存在
	 * @param username
	 * @return
	 */
	public boolean permissionIsExist(int roleId,String permissionType){
		
		if(permissionType != null || !"".equals(permissionType)){
			 Permission permissionInfo = myuserDaoJdbc.getPermissionInfo(roleId,permissionType);
			 if(permissionInfo.getPermission_name() == null || "".equals(permissionInfo.getPermission_name())){
				 return false;
			 }
		}

		 return true;
	}
	
	/**
	 * 获取用户权限信息
	 * @param username
	 * @return
	 */
	public Permission getPermissionInfo(int roleId,String permissionType){

		 String sql = "SELECT p.name as permission_name,p.guard_name as permission_guard_name,r.name as role_name,r.guard_name as role_guard_name FROM roles r,permissions p,role_has_permissions rh WHERE r.id = rh.role_id AND p.id = rh.permission_id AND r.id = ? AND p.name = ?";
		 try{
			 Permission psermission = (Permission)myuserDaoJdbc.getJdbcTemplate().queryForObject(sql, new Object[]{roleId,permissionType}, new PermissionRowMapper());
			 return psermission;
		}catch(EmptyResultDataAccessException e){
			return new Permission();
		}
	}

	
	/**
	 * 查询权限信息
	 * @author Administrator
	 *
	 */
	class PermissionRowMapper implements RowMapper<Permission> {
		@Override
		public Permission mapRow(ResultSet rs, int index) throws SQLException {

			Permission permission = new Permission();
			permission.setPermission_name(rs.getString("permission_name"));
			permission.setPermission_guard_name("permission_guard_name");
			permission.setRole_name("role_name");
			permission.setRole_guard_name("role_guard_name");

			return permission;
		}
	}
}
 

3配置/cas-server-webapp/src/main/webapp/WEB-INF/deployerConfigContext.xml

<bean id="authenticationManager"
		class="org.jasig.cas.authentication.PolicyBasedAuthenticationManager">
		<constructor-arg>
			<map>
				<entry key-ref="proxyAuthenticationHandler" value-ref="proxyPrincipalResolver" />
				<!--  将自定义的认证器配置进来 -->
				<entry key-ref="MyUserAuthenticationHandler" value-ref="primaryPrincipalResolve" /> 
			</map>
		</constructor-arg>

	<bean id="MyUserAuthenticationHandler"
		class="com.msxf.sso.authentication.MyUserAuthenticationHandler"/>  
		

	<bean id="primaryPrincipalResolve"
		class="org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver">
		<property name="attributeRepository" ref="attributeRepositoryer" />
	</bean>
	<!--  自定义的返回数据 -->
	<bean id="attributeRepositoryer" class="com.msxf.sso.authentication.MyUserStubPersonAttributeDao"/>
	
相关标签: CAS4.0 LDAP