13. Shiro整合CAS

2019-08-26  本文已影响0人  不知名的蛋挞

Shiro整合CAS

shiro是现在最为流行的权限认证管理框架,但是现在已经不再是最为传统的shiro处理处理了,因此此时的处理牵扯到了CAS实现认证的操作部分,所以对于shiro而言,它依然需要实现认证与授权检测,但是这个时候的认证应该交由CAS完成。

在现实的开发过程中,客户端是不可能直接访问CAS服务器的。WEB客户端其实就是CAS客户端,CAS客户端如果想和CAS服务器正常通讯,它就必须有一个证书。所以在整个处理流程里面就首先要有一个证书的操作配置。这个证书配置在JDK上,所以这个CAS客户端必须运行好配置好证书的JDK上。

我们这次测试模拟 web浏览器——>web服务器(CAS客户端)CAS客户端——>CAS服务器 使用的协议不一样,一个是http,一个是https。因为现在两边的协议不一样,你在整个过程中还需要对CAS服务器进行一次变革,才能让它支持HTTP的协议跳板。

(1)整合前准备

1. 需要在本地的windows系统的JDK里面导入服务器端证书

keytool -import -alias server -file d:\server.cer -keystore "%JAVA_HOME\jre\lib\security\cacerts%" -storepass changeit
keytool -list -keystore "%JAVA_HOME\jre\lib\security\cacerts%" -storepass changeit

搜索一下是否有cas.com

2. 修改cas的配置文件,让其支持http协议访问

vim /usr/local/tomcat/webapps/cas/WEB-INF/classes/services/HTTPSandIMAPS-10000001.json
默认只支持https 追加支持http

然后重新启动服务器。那么此时将支持协议访问的路径。

(2)实现CasRealm

2.1 导入shiro与cas整合的处理包开发包

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-cas</artifactId>
    <version>1.3.1</version>
</dependency>

2.2 修改数据库脚本

当前使用的数据表需要包含有角色、权限等信息

2.3 此时所有的查询内容都将交由CAS负责,而shiro只是负责角色与权限数据的获取

范例:定义一个MemberCasRealm程序类,需要继承CasRealm父类。

public class MemberCasRealm extends CasRealm {

    @Autowired
    private MemberService memberService;

    /**
     * 用户身份认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 此时接收的AuthenticationToken对象实际上是CasToken类型
        CasToken casToken = (CasToken)token;  // 现在需要返回的是CAS认证标记
        if(casToken==null){   // 如果现在没有返回token标记
            return null;  // 当前的登录失败
        }

        // CAS一定要返回给用户一个票根,所以需要取得这个票根的内容
        String ticket = (String)casToken.getCredentials();
        // 需要对票根的有效性进行验证
        if(!StringUtils.hasText(ticket)){  // 票根验证失败
            return null;  // 当前的登录失败
        }

        // 如果现在票根验证的格式正确,那么需要进行票根的有效性验证
        TicketValidator ticketValidator = super.ensureTicketValidator();

        try {
            // 首先需要针对于票根的CAS做一个验证处理
            Assertion casAssertion = ticketValidator.validate(ticket,super.getCasService());
            // 当验证处理完成之后,应该通过CAS取得用户信息
            AttributePrincipal casPrincipal = casAssertion.getPrincipal();
            String mid = casPrincipal.getName();  // 取出当前登录的用户名
            // 取出用户名之后需要将所有的相关信息(包括CAS相关信息)一起进行一个列表的创建
            List principals = CollectionUtils.asList(mid,casPrincipal.getAttributes());
            PrincipalCollection principalCollection = new SimplePrincipalCollection();
            return new SimpleAuthenticationInfo(principalCollection,ticket);
        } catch (TicketValidationException e) {
            e.printStackTrace();
        }
        return super.doGetAuthenticationInfo(token);
    }

    /**
     * 用户授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String userName = (String)principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo auth = new SimpleAuthorizationInfo();

        try {
           Map<String,Object> map = this.memberService.listAuthByMember(userName);
           Set<String> allRoles = (Set<String>)map.get("allRoles");
           Set<String> allActions = (Set<String>)map.get("allActions");
           auth.setRoles(allRoles);
           auth.setStringPermissions(allActions);
        } catch (TicketValidationException e) {
            e.printStackTrace();
        }
        return auth;
    }
}

此时对于使用的Realm只有用户认证部分发生了变化,而角色和权限的操作依然像之前那样直接通过业务层读取完成。

(3)环境配置

3.1 修改database.propeties文件

db.driver=org.ght.mm.mysql.Driver
db.url=jdbc:mysql://192.168.122.204:3306/shriodb
db.user=root
db.password=root

3.2 修改spring-shiro.xml文件

修改当前的Realm使用类型

<!-- 配置Realm -->
<bean id="memberRealm" class="com.web.cas.MemberCasRealm"/>

3.3 配置CAS的访问路径

<!-- 配置Realm -->
<bean id="memberRealm" class="com.web.cas.MemberCasRealm">
     <!--配置cas服务器的地址-->
     <property name="casServerUrlPrefix" value="https://cas.com"/>
     <!-- 客户端的回调地址设置,必须和下面的shiro-cas过滤器拦截的地址一致 -->
     <property name="casService" value="http://shiro.com/shirodemo/shiro-cas"/>
</bean>

3.4 配置CAS的访问过滤器

service=cas客户端回调地址

<bean id="casFilter" class="org.apache.shiro.cas.CasFilter">
        <!-- 登录失败后的访问路径,应该设置为cas.com访问 -->
        <property name="failureUrl" value="https://cas.com/login/service=http://shiro.com/shirodemo/shiro-cas"/>
</bean>

3.5 配置CAS注销的访问过滤器

注销就不能再回到回调页面了(总不能注销了再回来吧),所以我们重定向到首页。

<bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">
        <property name="redirectUrl" value="https://cas.com/logout?service=http://shiro.com/shirodemo/index.jsp"/>
</bean>

3.6 修改shiro过滤器

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <!--出现错误之后的跳转路径的配置-->
        <property name="loginUrl" value="https://cas.com/logout?service=http://shiro.com/shirodemo/shiro-cas"/>
        <!--认证失败之后的跳转路径页面-->
        <property name="unauthorizedUrl" value="/unauthUrl.action"/>
        <!--登录成功之后的跳转访问路径-->
        <property name="successUrl" value="/hello.action"/>
        <property name="filters">
            <map>
                <entry key="casFilter" value-ref="casFilter"/>
                <entry key="logoutFilter" value-ref="logout"/>
            </map>
        </property>
        <property name="filterChainDefinitions">
            <value>
                /shiro-cas = casFilter
                /loginUrl.action=authc
                /*=anon
                /message/**=authc
            </value>
        </property>
    </bean>

3.7 修改hosts文件

所有的访问都是以域名的方式出现的,所以还需要修改hosts文件,追加域名

127.0.0.1 shiro.com

(4)测试

访问shiro.com的首页

输入用户名和密码,从控制台可以看到已经进行了登陆的认证:

登录之后访问需要授权的页面,后台会出现角色和权限的信息查询提示信息。

CAS配置Remember me

如果要想配置rememberMe的操作需要考虑到两个配置部分:shiro(客户端)、cas(认证端)

1. 修改applicationContext.xml文件,为其追加一个工厂类

<bean id="securityManager" class="com.vip.vpao.web.cas.VpaoVisSecurityManager">
        <property name="subjectFactory" ref="sSubjectFactory"/>
        <!--其他配置省略-->
    </bean>

<!-- 如果要实现cas的remember me的功能,需要用到下面这个bean,并设置到securityManager的subjectFactory中 -->
<bean id="subjectFactory" class="org.apache.shiro.cas.CasSubjectFactory"/>

2. 修改deployerConfigContext.xml配置文件

对里面的认证管理器authenticationManager进行配置


<bean id="authenticationManager" class="org.jasig.cas.authentication.PolicyBasedAuthenticationManager">
        <constructor-arg>
            <map>
                <entry key-ref="proxyAuthenticationHandler" value-ref="proxyPrincipalResolver" />
                <!-- <entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" /> -->
                <entry key-ref="dbAuthHandler" value-ref="primaryPrincipalResolver"/>
            </map>
        </constructor-arg>
 
        <!-- 添加remember me配置-->
        <property name="authenticationMetaDataPopulators">
           <util:list>
              <bean class="org.jasig.cas.extension.clearpass.CacheCredentialsMetaDataPopulator"
                    c:credentialCache-ref="encryptedMap" />
           </util:list>
        </property>
        
        <property name="authenticationPolicy">
            <bean class="org.jasig.cas.authentication.AnyAuthenticationPolicy" />
        </property>
</bean>

3. 修改另外一个页面的配置文件:cas\WEB-INF\webflow\login\login-webflow.xml

找到viewLoginForm表单,里面加上rememberMe标签:

<view-state id="viewLoginForm" view="casLoginView" model="credential">
        <binder>
            <binding property="username" />
            <binding property="password" />
            <binding property="captcha" />
            <binding property="rememberMe" />
        </binder>
        <on-entry>
            <set name="viewScope.commandName" value="'credential'" />
        </on-entry>
        <transition on="submit" bind="true" validate="true" to="validatorCaptcha">
            <evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credential)" />
        </transition>
</view-state>

4. 修改“cas\WEB-INF\spring-configuration\ticketExpirationPolicies.xml”文件(票根过期的配置文件)

替换原有的grantingTicketExpirationPolicy的bean为如下内容:

<bean id="grantingTicketExpirationPolicy" class="org.jasig.cas.ticket.support.RememberMeDelegatingExpirationPolicy">
   <property name="sessionExpirationPolicy">
    <bean class="org.jasig.cas.ticket.support.TimeoutExpirationPolicy">
           <constructor-arg index="0" value="XXXXXXXX" />
    </bean>
   </property>
   <property name="rememberMeExpirationPolicy">
    <bean class="org.jasig.cas.ticket.support.TimeoutExpirationPolicy">
           <constructor-arg index="0" value="XXXXXXXX" />
    </bean>
   </property>
</bean>

其实就是修改ticket过期策略。

5. rememberMe需要找到cookie,所以需要修改“cas\WEB-INF\spring-configuration\ticketGrantingTicketCookieGenerator.xml”文件

在ticketGrantingTicketCookieGenerator的bean中增加 p:rememberMeMaxAge="7200000",设定rememberMe保存的最长时间。

要注意的是这里的7200000为秒数。并且要注意和上面 ticketExpirationPolicies.xml中设置的保持一致。

6. 此时对于记住我这个信息实际上还没有提示内容,所以需要修改一个资源文件

\u8BB0\u4F4F\u6211是中文“记住我”的转码

7. 修改页面显示文件

8. 测试

上一篇下一篇

猜你喜欢

热点阅读