一、cas實現經過ad域進行認證java
搭cas服務器環境,配置一下deployerConfigContext.xml便可,至關簡單,上代碼!導證書啥的本身百度,我以前文章也介紹過,很簡單。再也不多說,我是使用ldap進行認證的,若是使用數據庫認證請百度,配置很好改的。web
<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>
二、jeesite和cas進行結合(shiro和cas的結合)spring
這裏纔是重點,真的是折磨了我很久啊。。。數據庫
先上配置文件,只上傳改動的,有問題私信我.apache
記住很是重要的一點、很是重要的一點、很是重要的一點緩存
loginUrl,這裏service=「http://10.10.10.10:8080/iqilu${adminPath}/cas」,引號裏面的內容要和casService是保持一致的。tomcat
<!-- 安全認證過濾器 --> <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.session
這個和之間寫的用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:部署項目上線
一、用keytools工具,根據域名生成cas的證書,sso.xx.com,不能用ip;(改本地host便可經過域名訪問)
二、須要把cas生成的證書經過keytools工具導入\jdk1.7.0_75\jre\lib\security\cacerts 中,如何本地已經導入證書能夠直接複製本地覆蓋環境的便可;
三、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去掉看看代碼是否正常運行,看看配置文件是否配置正確
最近你們留言在配置時各類問題,我也是拿來主義,用到什麼學什麼,學的比較淺,有的問題的確解答不了。