CAS集成Shiro的配置方法 -- 知识铺
由于工作上的要求所以一直在寻找一些符合要求的集成方法,虽然不是自己发现的,但是有些问题经过研究更正。
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>
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/geek001/post/20240428/CAS%E9%9B%86%E6%88%90Shiro%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95--%E7%9F%A5%E8%AF%86%E9%93%BA/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com