CAS-使用Shiro+buji pac4j集成CAS客户端的配置

由于工作上的要求所以一直在寻找一些符合要求的集成方法,虽然不是自己发现的,但是有些问题经过研究更正。

1、配置web.xml
由于CAS的一个子系统Logout以后其他子系统并没有同步退出,所以这里面加入了,cas官方的集成监听器和过滤器

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
  <display-name>Struts Blank</display-name>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
	        	classpath:spring-mvc.xml
	        </param-value>
  </context-param>
  <servlet>
    <servlet-name>UploadHandleServlet</servlet-name>
    <servlet-class>me.gacl.web.controller.UploadHandleServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>UploadHandleServlet</servlet-name>
    <url-pattern>/servlet/UploadHandleServlet</url-pattern>
  </servlet-mapping>
  <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <filter>
		<filter-name>shiroFilter</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
		<init-param>
			<param-name>targetFilterLifecycle</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>shiroFilter</filter-name>
		<url-pattern>/*</url-pattern>
		<dispatcher>REQUEST</dispatcher>
		<dispatcher>FORWARD</dispatcher>
	</filter-mapping>
</web-app>

2、cas_client的pom.xml文件

        <!-- buji pac4j-->
        <dependency>
			<groupId>io.buji</groupId>
			<artifactId>buji-pac4j</artifactId>
			<version>${bujiVersion}</version>
		</dependency>
        
        <!-- shiro -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-web</artifactId>
			<version>${shiro.version}</version>
		</dependency>		
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-ehcache</artifactId>
			<version>${shiro.version}</version>
			<exclusions>
				<exclusion>
					<artifactId>ehcache-core</artifactId>
					<groupId>net.sf.ehcache</groupId>
				</exclusion>
			</exclusions>
		</dependency>	
        <!-- CAS -->
       <dependency>
            <groupId>org.jasig.cas.client</groupId>
            <artifactId>cas-client-core</artifactId>
            <version>3.5.1</version>
        </dependency>

3、集成重写DefaultCasLogoutHandler和Pac4jRealm两个类
①DefaultCasLogoutHandler

package com.mongodb.util;

import org.pac4j.cas.logout.DefaultCasLogoutHandler;
import org.pac4j.core.context.WebContext;
import org.pac4j.core.context.session.SessionStore;
import org.pac4j.core.store.Store;

import io.buji.pac4j.profile.ShiroProfileManager;

public class ShiroCasLogoutHandler<C extends WebContext> extends DefaultCasLogoutHandler<C> {

	public ShiroCasLogoutHandler() {
    }

    public ShiroCasLogoutHandler(final Store<String, Object> store) {
        super(store);
    }

    protected void destroy(final C context, final SessionStore sessionStore, final String channel) {
        // remove profiles
        final ShiroProfileManager manager = new ShiroProfileManager(context);
        manager.logout();
        logger.debug("destroy the user profiles");
        // and optionally the web session
        if (isDestroySession()) {
            logger.debug("destroy the whole session");
            final boolean invalidated = sessionStore.destroySession(context);
            if (!invalidated) {
                logger.error("The session has not been invalidated for {} channel logout", channel);
            }
        }
    }
}

②Pac4jRealm

package com.mongodb.util;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.bson.Document;
import org.pac4j.core.profile.CommonProfile;
import org.springframework.beans.factory.annotation.Autowired;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import io.buji.pac4j.realm.Pac4jRealm;
import io.buji.pac4j.subject.Pac4jPrincipal;
import io.buji.pac4j.token.Pac4jToken;

public class ShiroCASPac4jRealm extends Pac4jRealm {
    //该方法可以获取到cas服务端的多属性返回的属性
	@Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
		
        final Pac4jToken token = (Pac4jToken) authenticationToken;
        final List<CommonProfile> profiles = token.getProfiles();

        final Pac4jPrincipal principal = new Pac4jPrincipal(profiles, getPrincipalNameAttribute());
        final PrincipalCollection principalCollection = new SimplePrincipalCollection(principal, getName());
        
        String loginName = principal.getProfile().getId(); 
        Session session = SecurityUtils.getSubject().getSession(true);
		session.setAttribute("user", loginName);
        return new SimpleAuthenticationInfo(principalCollection, profiles.hashCode());
    }
	

	@Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
      
		//获取当前登录输入的用户名,等价于(String) principalCollection.fromRealm(getName()).iterator().next(); 
        Session session = SecurityUtils.getSubject().getSession(); 
        //  Account user = Account.class.cast(session.getAttribute(Const.SESSION_USER));

        final SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addRoles(new ArrayList<String>());
        return simpleAuthorizationInfo;
	}
}

4、配置shiro-pac4j.properties

##cas服务前缀
sso.cas.server.prefixUrl=http://服务端URL/cas/
##cas服务登录url
sso.cas.server.loginUrl=http://服务端URL/cas/login
##cas客户端回调地址
sso.cas.client.callbackUrl=http://客户端URL/casClient/callback?client_name=msrRim
##cas服务端成功跳转地址
sso.cas.client.successUrl=http://客户端URL/casClient/user2/showshiti
##登出后地址
sso.cas.client.logoutUrl=http://服务端URL/cas/login

5、配置shiro-cas-pac4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:c="http://www.springframework.org/schema/c"
	xmlns:cache="http://www.springframework.org/schema/cache"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc"
	xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:lang="http://www.springframework.org/schema/lang"
	xmlns:mongo="http://www.springframework.org/schema/data/mongo"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:repository="http://www.springframework.org/schema/data/repository"
	xmlns:stat="http://www.alibaba.com/schema/stat"
	xmlns:task="http://www.springframework.org/schema/task"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:websocket="http://www.springframework.org/schema/websocket"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
		http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-4.3.xsd
		http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-2.0.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
		http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
		http://www.springframework.org/schema/data/repository http://www.springframework.org/schema/data/repository/spring-repository-2.1.xsd
		http://www.alibaba.com/schema/stat http://www.alibaba.com/schema/stat.xsd
		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd
		http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket-4.3.xsd">

	<!-- Session和Cookie -->
	<bean id="sessionIdGenerator"
		class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator" />
	<bean id="sessionIdCookie"
		class="org.apache.shiro.web.servlet.SimpleCookie">
		<constructor-arg value="sssid" />
		<property name="httpOnly" value="false" />
		<property name="maxAge" value="1800" />
		<property name="path" value="/" />
	</bean>
	<bean id="sessionDAO"
		class="org.apache.shiro.session.mgt.eis.MemorySessionDAO">
		<property name="sessionIdGenerator" ref="sessionIdGenerator" />
	</bean>
	<bean id="sessionValidationScheduler"
		class="org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler">
		<property name="interval" value="1800000" />
	</bean>
	<!-- Realm -->
	<bean id="Pac4jRealm" class="com.mongodb.util.ShiroCASPac4jRealm">
		<property name="cachingEnabled" value="false" />
		<property name="authenticationCachingEnabled" value="false" />
		<property name="authenticationCacheName"
			value="authenticationCache" />
		<property name="authorizationCachingEnabled" value="false" />
		<property name="authorizationCacheName"
			value="authorizationCache" />
	</bean>
	<!-- 可配置多个Realm -->
	<bean id="authenticator"
		class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
		<property name="realms">
			<list>
				<ref bean="Pac4jRealm" />
			</list>
		</property>
		<property name="authenticationStrategy">
			<bean class="org.apache.shiro.authc.pam.FirstSuccessfulStrategy"></bean>
		</property>
	</bean>
	<!-- 基于pac4j的Subject工厂 -->
	<bean id="pac4jSubjectFactory"
		class="io.buji.pac4j.subject.Pac4jSubjectFactory"></bean>
	<!-- 安全管理器 -->
	<bean id="securityManager"
		class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="authenticator" ref="authenticator"></property>
		<property name="subjectFactory" ref="pac4jSubjectFactory"></property>
	</bean>


	<!-- cas服务端 -->
	<bean id="casLogoutHandler"
		class="com.mongodb.util.ShiroCasLogoutHandler">
		<property name="destroySession" value="true"></property>
	</bean>
	<bean id="casConfig" class="org.pac4j.cas.config.CasConfiguration">
		<!-- CAS server登录链接 -->
		<property name="loginUrl" value="${sso.cas.server.loginUrl}"></property>
		<!-- CAS server服务前缀 -->
		<property name="prefixUrl"
			value="${sso.cas.server.prefixUrl}"></property>
		<!-- 登出处理器,单点登出时所需要的操作在这里实现 -->
		<property name="logoutHandler" ref="casLogoutHandler"></property>
	</bean>
	<!-- 配置cas客户端 -->
	<bean id="msrRim" class="org.pac4j.cas.client.CasClient">
		<property name="name" value="msrRim"></property>
		<constructor-arg ref="casConfig" />
		<!-- 客户端回调地址 -->
		<property name="callbackUrl"
			value="${sso.cas.client.callbackUrl}"></property>
	</bean>
	<!-- pac4j配置 -->
	<bean id="sessionStore"
		class="io.buji.pac4j.context.ShiroSessionStore"></bean>
	<bean id="authcConfig" class="org.pac4j.core.config.Config">
		<constructor-arg ref="msrRim"></constructor-arg>
		<property name="sessionStore" ref="sessionStore"></property>
	</bean>

	<!-- Shiro Filter, 在web.xml中被部署 -->
	<bean id="shiroFilter"
		class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<property name="securityManager" ref="securityManager" />
		<property name="filters">
			<util:map>
				<!-- 配置SecurityFilter,用于拦截受保护的url -->
				<entry key="casSecurityFilter">
					<bean class="io.buji.pac4j.filter.SecurityFilter">
						<property name="config" ref="authcConfig"></property>
						<property name="clients" value="msrRim"></property>
					</bean>
				</entry>
				<!-- 回调过滤器,完成ticket认证 -->
				<entry key="callback">
					<bean class="io.buji.pac4j.filter.CallbackFilter">
						<property name="config" ref="authcConfig"></property>
						<property name="defaultUrl" value="${sso.cas.client.successUrl}"></property>
					</bean>
				</entry>
				<!-- 登出过滤器 -->
				<entry key="logout">
					<bean id="logout" class="io.buji.pac4j.filter.LogoutFilter">
						<property name="defaultUrl" value="${sso.cas.client.logoutUrl}"></property>
						<property name="config" ref="authcConfig"></property>
						<property name="centralLogout" value="true"></property>
						<property name="localLogout" value="false"></property>
					</bean>
				</entry>
			</util:map>
		</property>

		<property name="filterChainDefinitions">
			<value>
				/index =  casSecurityFilter
				/callback = callback
				/static/** = anon
				/logout = logout
				/** = authc
			</value>
		</property>
	</bean>

	<!-- 生命周期处理 -->
	<bean id="lifecycleBeanPostProcessor"
		class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

	<bean id="annotationProxy"
		class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
		depends-on="lifecycleBeanPostProcessor">
		<property name="proxyTargetClass" value="true" />
	</bean>
</beans>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值