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&characterEncoding=utf8&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"/>
上一篇: 图解TCP/IP:路径MTU发现