文档章节

【和我一起学jeesite】jeesite结合CAS做单点登录

hello_bear
 hello_bear
发布于 2016/06/17 14:30
字数 1539
阅读 3068
收藏 2

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去掉看看代码是否正常运行,看看配置文件是否配置正确

最近大家留言在配置时各种问题,我也是拿来主义,用到什么学什么,学的比较浅,有的问题的确解答不了。

© 著作权归作者所有

共有 人打赏支持
hello_bear
粉丝 10
博文 48
码字总数 14912
作品 0
海淀
私信 提问
加载中

评论(12)

jeesite 快速开发平台 初体验

http://www.jeesite.com/ GitHub:https://github.com/thinkgem/jeesite 开源中国:http://git.oschina.net/thinkgem/jeesite 更多文档 https://github.com/thinkgem/jeesite/tree/master/do......

晨猫
05/21
0
0
jeesite配置指南(官方文档有坑,我把坑填了!)

版权声明:欢迎转载,请注明沉默王二原创。 https://blog.csdn.net/qing_gee/article/details/72871340 昨天,远在苏州的朋友找我一起做个私活,主要用到jeesite。 说实话,开发了这么多年的...

qing_gee
2017/06/05
0
0
ThinkGem/JeeSite4 Spring Cloud

引言 JeeSite Spring Cloud 是基于 Spring Cloud Finchley 的一个分布式系统套件的整合。 特点:用经典开发模式,开发分布式应用,两个字【简单】,一个字【快】。 技术选型 分布式系统主框架...

ThinkGem
12/07
0
0
JeeSite环境搭建及运行和打包(master20161117)

涉及的软件: 1、phpStudy(主要用MySql) 2、maven3(用于依赖包,下面我将上传已经下载好所有依赖包的版本,保证运行正常) 具体操作: 0、前言 由于GitHub上的Release版本没有及时更新,所...

easonjim
2016/11/18
0
0
分布式系统套件的整合 - JeeSite Spring Cloud

引言 JeeSite Spring Cloud 是基于 Spring Cloud Finchley 的一个分布式系统套件的整合。 特点:用经典开发模式,开发分布式应用,两个字【简单】,一个字【快】。 技术选型 分布式系统主框架...

ThinkGem
11/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

jquery通过id显示隐藏

var $div3 = $('#div3'); 显示 $div3.show(); 隐藏 $div3.hide();

yan_liu
今天
3
0
《乱世佳人》读书笔记及相关感悟3900字

《乱世佳人》读书笔记及相关感悟3900字: 之前一直听「荔枝」,后来不知怎的转向了「喜马拉雅」,一听就是三年。上班的时候听房产,买房了以后听装修,兴之所至时听旅行,分手后听亲密关系,...

原创小博客
今天
3
0
大数据教程(9.6)map端join实现

上一篇文章讲了mapreduce配合实现join,本节博主将讲述在map端的join实现; 一、需求 实现两个“表”的join操作,其中一个表数据量小,一个表很大,这种场景在实际中非常常见,比如“订单日志...

em_aaron
今天
3
0
cookie与session详解

session与cookie是什么? session与cookie属于一种会话控制技术.常用在身份识别,登录验证,数据传输等.举个例子,就像我们去超市买东西结账的时候,我们要拿出我们的会员卡才会获取优惠.这时...

士兵7
今天
3
0
十万个为什么之为什么大家都说dubbo

Dubbo是什么? 使用背景 dubbo为什么这么流行, 为什么大家都这么喜欢用dubbo; 通过了解分布式开发了解到, 为适应访问量暴增,业务拆分后, 子应用部署在多台服务器上,而多台服务器通过可以通过d...

尾生
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部