简介

  • Shiro 1.2开始支持Jasig CAS单点登录。
  • 作用:用户只需要到一个中央服务器登录一次即可访问这些系统中的任何一个,无需多次登录。

服务器下载

  • 注销: https://localhost:8443/cas/logout

  • 以上只是测试cas server的效果,下面正式集成cas,分为server和client两部分。

  • 新建Maven项目:shiro-chapter15。

CAS Server

  • 直接将E:\cas-server-4.0.0-release\cas-server-4.0.0\cas-server-webapp拷到shirochapter15下成为其子模块,并重命名为shiro-chapter15-server;idea将自动扫描到更改。
  • 在idea中修改shiro-chapter15的pom.xml,设置shiro-chapter15-server为其子模块。
  • 修改shiro-chapter15-server的pom.xml中的一些头信息,增加tomcat插件。
  • 添加证书:src下建包licensing,把E:\cas导入maven缺少head.txt文件中俩文件复制进去即可。
  • 添加自定义用户:src/main/webapp/WEB-INF/deployerConfigContext.xml,primaryAuthenticationHandler节点下添加代码:

    <entry key="zhang" value="123"/>
    
  • tomcat7:run运行,出现上面登录界面,输入zhang/123即可登录。cas server配置成功。

CAS Client

  • 示例采用shirochapter12,web.xml、pom.xml、src、resources下文件基本一致,以下只列出不同的部分。
  • 导出证书:cas客户端和服务端间交互需要用到证书,因此需要将D:/keys/localhost.keystore导出证书到相同目录下。
//导出证书
keytool -export -alias localhost -file D:\keys\localhost.cer 
    -keystore D:\keys\localhost.keystore
//导入jdk
cd D:\jdk\1.8\jre\lib\security //进入jdk(真正的jdk而非本地jdk目录)
keytool -import -alias localhost 
    -file D:\localhost.cer -noprompt -trustcacerts -storetype jks 
    -keystore cacerts -storepass 123456
  • 导入失败的话可先将security下的cacerts删掉。

  • 导入shiro-cas依赖:

    <dependency> <!--集成cas-client-->
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-cas</artifactId>
        <version>1.2.2</version>
    </dependency>
    
  • 自定义CasRealm:继承CasRealm类,实现权限验证,用户验证则交给cas server做,不用自定义。

public class MyCasRealm extends CasRealm {
    private UserService userService;

    public void setUserService(UserService userService){
        this.userService=userService;
    }

    /**
     * @Author haien
     * @Description 根据CAS服务器返回的用户身份获取相应的权限信息
     * @Date 2019/3/11
     * @Param [principals]
     * @return org.apache.shiro.authz.AuthorizationInfo
     **/
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username=(String)principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();
        authorizationInfo.setRoles(userService.findRoles(username));
        authorizationInfo.setStringPermissions(userService.findPermissions(username));
        return authorizationInfo;
    }
}
  • spring-shiro-web.xml:配置CasRealm和CasFilter,即查找用户权限以支持权限验证和配置cas过滤器使登录时重定向到cas server的登录页面。

    <!--CasRealm-->
    <bean id="casRealm" class="com.haien.chapter15.realm.MyCasRealm">
        <property name="userService" ref="userService"/>
        <property name="cachingEnabled" value="true"/>
        <property name="authenticationCachingEnabled" value="true"/>
        <property name="authenticationCacheName" value="authenticationCache"/>
        <property name="authorizationCachingEnabled" value="true"/>
        <property name="authorizationCacheName" value="authorizationCache"/>
        <!--CAS Server服务器端地址-->
        <property name="casServerUrlPrefix" value="https://localhost:8443/chapter15-server"/>
        <!--登录成功后跳转的url,即用于接收并处理登录成功后的Ticket的-->
        <property name="casService" value="https://localhost:8443/chapter15-client/cas"/>
    </bean>
    
  • 如果用户权限信息也由服务端提供的话,可以不用继承而直接使用CasRealm。

    <bean id="casRealm" class="org.apache.shiro.cas.CasRealm">
    
        <!--和上面一样的property-->
    
        <!--默认添加给所有登录成功用户的角色和权限-->
        <property name="defaultRoles" value="admin,user"/>
        <property name="defaultPermissions" value="user:create,user:update"/>
    
        <!--角色、权限字段名;若权限信息是从服务端返回的(即返回的CAS Principal中
        除了Principal外还有Attributes),可以使用roleAttributeNames、
        permissionAttributeNames来获取Attributes中的角色、权限信息;
        请自行查询cas如何获取用户更多信息-->
        <property name="roleAttributeNames" value="roles"/>
        <property name="permissionAttributeNames" value="permissions"/>
    </bean>
    
  • CasFilter:

    <!--CasFilter:类似于FormAuthenticationFilter,只不过其验证服务器端返回的是
    CAS Service Ticket-->
    <bean id="casFilter" class="org.apache.shiro.cas.CasFilter">
        <property name="failureUrl" value="/casFailure.jsp" />
    </bean>
    
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <!--登录路径;service为登录成功后跳转的url-->
        <property name="loginUrl" value="https://localhost:8443/chapter15-server/login?
            service=https://localhost:8443/chapter15-client/cas"/>
        <!-- 登录成功后跳转路径 -->
        <property name="successUrl" value="/" />
        <!--定义自己的过滤器-->
        <property name="filters">
            <util:map>
                <entry key="cas" value-ref="casFilter"/>
            </util:map>
        </property>
        <property name="filterChainDefinitions">
            <value>
                /casFailure.jsp=anon
                /cas=cas //走cas服务器,带着ticket过去再次身份验证
                /logout = logout
                /** = user
            </value>
        </property>
    </bean>
    
  • 测试:

  1. 访问http://localhost:8080/chapter15-client/,自动跳转登录页面,即在spring-shiro-web.xml
    配置的loginUrl————https://localhost:8443/server/login?service=
    https://localhost:8443/chapter15-client/cas,原url从/变成/cas;
  2. 登录成功后,转回原url:https://localhost:8443/chapter15-client/cas?ticket=
    ST-1-eh2cIo92F9syvoMs5DOg-cas01.example.org;
  3. spring-shiro-web.xml配置了/cas要走cas过滤器,它会先验证ticket是否有效,有效再调用MyCasRealm获取权限信息。