1、cas实现通过ad域进行认证
搭cas服务器环境,配置一下deployerConfigContext.xml即可,相当简单,上代码!导证书啥的自己百度,我之前文章也介绍过,很简单。不再多说,我是使用ldap进行认证的,如果使用数据库认证请百度,配置很好改的。
<bean id="authenticationManager"
class="org.jasig.cas.authentication.AuthenticationManagerImpl">
<property name="credentialsToPrincipalResolvers">
<list>
<bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" >
<property name="attributeRepository" ref="attributeRepository" />
</bean>
<bean class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver" />
</list>
</property>
<property name="authenticationHandlers">
<list>
<bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" p:httpClient-ref="httpClient" />
<!-- <bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" /> -->
<!-- 通过ad域进行认证 @autor qiaojinjian -->
<bean class="org.jasig.cas.adaptors.ldap.BindLdapAuthenticationHandler">
<property name="filter" value="sAMAccountName=%u" />
<!-- 基节点 -->
<property name="searchBase" value="ou=xxx,DC=xxx,DC=local" />
<property name="contextSource" ref="contextSource" />
</bean>
</list>
</property>
</bean>
<!-- 数据源 @autor qiaojinjian -->
<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="password" value="xxx />
<property name="pooled" value="true" />
<property name="url" value="ldap://10.10.10.10:389" />
<!--管理员 -->
<property name="userDn" value="cn=readwrite,dc=xxx,dc=local" />
<property name="baseEnvironmentProperties">
<map>
<entry key="com.sun.jndi.ldap.connect.timeout" value="60" />
<entry key="com.sun.jndi.ldap.read.timeout" value="60" />
<entry key="java.naming.security.authentication" value="simple" />
</map>
</property>
</bean>
2、jeesite和cas进行结合(shiro和cas的结合)
这里才是重点,真的是折磨了我好久啊。。。
先上配置文件,只上传改动的,有问题私信我.
记住非常重要的一点、非常重要的一点、非常重要的一点
loginUrl,这里service=“http://10.10.10.10:8080/iqilu${adminPath}/cas”,引号里面的内容要和casService是保持一致的。
<!-- 安全认证过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- securityManager是一个安全认证的总的容器,所有的安全相关的请求都会交给他来处理 -->
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="${cas.server.url}?service=http://10.10.10.10:8080/jeesite${adminPath}/cas" />
<property name="successUrl" value="${adminPath}?login" />
<property name="filters">
<map>
<entry key="cas" value-ref="casFilter"/>
<entry key="authc" value-ref="formAuthenticationFilter"/>
</map>
</property>
<property name="filterChainDefinitions">
<ref bean="shiroFilterChainDefinitions"/>
</property>
</bean>
<!-- cas和shiro结合 -->
<bean id="casRealm" class="com.thinkgem.jeesite.modules.sys.security.MyCasRealm" depends-on="userDao,roleDao,menuDao">
<property name="casServerUrlPrefix" value="https://sso.sdtv.cn:8443/CasServer"></property>
<property name="casService" value="http://10.10.10.10:8080/jeesite${adminPath}/cas"></property>
</bean>
<!-- 定义Shiro安全管理配置,securityManager里面是包括认证和授权等操作的.同时提供了会话管理以及缓存管理 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 这里主要是重写认证和授权的回调函数 -->
<property name="realm" ref="casRealm" />
<property name="sessionManager" ref="sessionManager" />
<property name="cacheManager" ref="shiroCacheManager" />
</bean>
配置文件之后就是自定义的casRealm了。
如果直接用casRealm的话,发现认证都过不去。。
一言不合上代码!MyCasRealm.
这个和之间写的用ad域进行认证的realm差不多。最重要的一点就是Principal,这个jeesite中很多地方都用到获取用户信息等,所以一定要按照这个Principal格式来返回SimpleAuthenticationInfo
package com.thinkgem.jeesite.modules.sys.security;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cas.CasAuthenticationException;
import org.apache.shiro.cas.CasRealm;
import org.apache.shiro.cas.CasToken;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.util.StringUtils;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.validation.Assertion;
import org.jasig.cas.client.validation.TicketValidationException;
import org.jasig.cas.client.validation.TicketValidator;
import com.thinkgem.jeesite.common.utils.SpringContextHolder;
import com.thinkgem.jeesite.common.web.Servlets;
import com.thinkgem.jeesite.modules.sys.entity.Menu;
import com.thinkgem.jeesite.modules.sys.entity.Role;
import com.thinkgem.jeesite.modules.sys.entity.User;
import com.thinkgem.jeesite.modules.sys.security.SystemAuthorizingRealm.Principal;
import com.thinkgem.jeesite.modules.sys.service.SystemService;
import com.thinkgem.jeesite.modules.sys.utils.LogUtils;
import com.thinkgem.jeesite.modules.sys.utils.UserUtils;
/**
* 自定义casRealm
* */
public class MyCasRealm extends CasRealm{
private SystemService systemService;
public MyCasRealm() {
super();
}
/**
* 认证
* */
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
CasToken casToken = (CasToken) token;
if (token == null)
return null;
String ticket = (String) casToken.getCredentials();
if (!StringUtils.hasText(ticket))
return null;
TicketValidator ticketValidator = ensureTicketValidator();
try {
Assertion casAssertion = ticketValidator.validate(ticket, getCasService());
//casPrincipal 认证后的用户信息
AttributePrincipal casPrincipal = casAssertion.getPrincipal();
String userId = casPrincipal.getName();
//获取用户
User user = getSystemService().getUserByLoginName(userId);
Map attributes = casPrincipal.getAttributes();
casToken.setUserId(userId);
String rememberMeAttributeName = getRememberMeAttributeName();
String rememberMeStringValue = (String) attributes.get(rememberMeAttributeName);
boolean isRemembered = rememberMeStringValue != null && Boolean.parseBoolean(rememberMeStringValue);
if (isRemembered)
casToken.setRememberMe(true);
List principals = CollectionUtils.asList(new Object[] { userId, attributes });
PrincipalCollection principalCollection = new SimplePrincipalCollection(principals, getName());
// 这里可以拿到Cas的登录账号信息,加载到对应权限体系信息放到缓存中...
return new SimpleAuthenticationInfo(new Principal(user, false), ticket,getName());
} catch (TicketValidationException e) {
throw new CasAuthenticationException((new StringBuilder()).append("Unable to validate ticket [")
.append(ticket).append("]").toString(), e);
}
}
/**
* 授权
* */
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
Principal principal = (Principal) getAvailablePrincipal(principals);
User user = getSystemService().getUserByLoginName(principal.getLoginName());
if (user != null) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
List<Menu> list = UserUtils.getMenuList();
for (Menu menu : list){
if (org.apache.commons.lang3.StringUtils.isNotBlank(menu.getPermission())){
// 添加基于Permission的权限信息
for (String permission : org.apache.commons.lang3.StringUtils.split(menu.getPermission(),",")){
info.addStringPermission(permission);
}
}
}
// 添加用户权限
info.addStringPermission("user");
// 添加用户角色信息
for (Role role : user.getRoleList()){
info.addRole(role.getEnname());
}
// 更新登录IP和时间
getSystemService().updateUserLoginInfo(user);
// 记录登录日志
LogUtils.saveLog(Servlets.getRequest(), "系统登录");
return info;
} else {
return null;
}
}
protected List split(String s) {
List list = new ArrayList();
String elements[] = StringUtils.split(s, ',');
if (elements != null && elements.length > 0) {
String arr$[] = elements;
int len$ = arr$.length;
for (int i$ = 0; i$ < len$; i$++) {
String element = arr$[i$];
if (StringUtils.hasText(element))
list.add(element.trim());
}
}
return list;
}
protected void addRoles(SimpleAuthorizationInfo simpleAuthorizationInfo, List roles) {
String role;
for (Iterator i$ = roles.iterator(); i$.hasNext(); simpleAuthorizationInfo.addRole(role))
role = (String) i$.next();
}
protected void addPermissions(SimpleAuthorizationInfo simpleAuthorizationInfo, List permissions) {
String permission;
for (Iterator i$ = permissions.iterator(); i$.hasNext(); simpleAuthorizationInfo
.addStringPermission(permission))
permission = (String) i$.next();
}
public SystemService getSystemService() {
if (systemService == null){
systemService = SpringContextHolder.getBean(SystemService.class);
}
return systemService;
}
}
有问题私信
好多人都私信我说重定向,我自己试了一下,一直没有问题,最近换了新电脑,发现也出现了重定向的问题,然后报错PKIX相关,一看就知道是证书的问题,然后把之前的证书导入jdk就可以了。
也有网友的帖子说把下面这句话去掉就可以了,测试了一下,没有影响。应该还是证书的问题
<property name="sessionManager" ref="sessionManager" />
事实证明:去掉这句话还是有用的,单点注销的时候,如果有这个会导致失败。
mark:部署项目上线
1、用keytools工具,根据域名生成cas的证书,sso.xx.com,不能用ip;(改本地host即可通过域名访问)
2、需要把cas生成的证书通过keytools工具导入\jdk1.7.0_75\jre\lib\security\cacerts 中,如何本地已经导入证书可以直接复制本地覆盖环境的即可;
3、tomcat的8443端口需要配置证书和密码,应该是第一步生成的;
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" keystoreFile="/usr/local/tomcat7/conf/cas2" keystorePass="cas123"/>
ps:最近更新环境发现有重定向问题,由于项目代码有问题导致重定向,可以先把cas去掉看看代码是否正常运行,看看配置文件是否配置正确
最近大家留言在配置时各种问题,我也是拿来主义,用到什么学什么,学的比较浅,有的问题的确解答不了。