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

    xiaoxiao2022-07-03  177

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

    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)