shiro+cas+tomcat在ssm项目中实现单点登陆

Shiro是一个强大且易用的JAVA框架,在保持强大功能的同时,还在简单性和灵活性方面拥有巨大优势。Shiro是一个强大而灵活的开源安全框架,能够非常清晰的处理认证、授权、管理会话以及密码加密。在单点登陆中,所有的WEB端安全验证都交由CAS完成,用以实现"单点登陆,遍地开花".

1.架构设计图
在这里插入图片描述
在此架构中,WEB浏览器和WEB服务端通过证书双向验证,CAS客户端与CAS服务器端进行证书双向验证.这样可以大大提高安全性,只有在证书相对应后,才可以判断出对方不是从中间进行拦截的黑客,从而实现数据的交互,CAS服务器端主要是从指定的数据库服务器中提取出用户身份认证和授权,而在授权完成后,还会将已被认证授权的角色传递给WEB端,预防频繁通过CAS服务器端验证,造成性能低下.

2.在WEB浏览器端JDK中加入证书
(1)进入jre安全目录

cd /usr/local/jdk1.8.0_101/jre/lib/security

(2)导入证书

keytool -import -alias server -keystore ./cacerts -file /srv/ftp/server.cer -trustcacerts

此时命令行会提示你输入cacerts证书库的密码,你敲入changeit就行了,这是java中cacerts证书库的默认密码

(3)删除证书,如果有需要

keytool -delete -alias 证书名 -keystore cacerts

(4)查看所有证书,如果有需要

keytool -list -keystore cacerts

3.修改cas服务配置,时期支持HTTP协议
在WEB服务端与CAS服务器端的连接中,使用了HTTPS协议,这次在客户端与WEB端中使用HTTP协议

(1)编辑配置文件

vim /usr/local/tomcat/webapps/cas/WEB-INF/classes/services/HTTPSandIMAPS-10000001.json

(2)在第三行内容加入http

 "serviceId" : "^(https|imaps)://.*"  -->  "serviceId" : "^(https|http|imaps)://.*",

那么此时代表已经可以支持HTTP协议

4.实现CasRealm

(1)首先设计角色权限表,用于CAS验证,角色权限表根据自身网站情况进行设计
在这里插入图片描述
仅供参考

(2)在CASRealm中,只有身份验证发生了变化,角色权限认证与传统shiro相似,因为身份验证需要票根等信息,附参考代码

public class MemberRealm extends CasRealm {
    public AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token){
        CasToken casToken=(CasToken)token;
        if (casToken==null){ //当令牌为空时候,说明未接收到用户名密码
            return null;//登陆失败
        }
        //在CAS服务器验证通过后,一定会返回一个票根,这个票根记录通过信息
        String ticket=(String) casToken.getCredentials();
        if (!StringUtils.hasText(ticket)){ //票根没有内容
            return null;//验证失败
        }
        try {
            //如果票根格式正确,就要检查它的有效性
            TicketValidator ticketValidator = super.ensureTicketValidator();
            //对于票根进行验证,返回一个结果
            Assertion assertion = ticketValidator.validate(ticket, super.getCasService());
            //取得用户信息
            AttributePrincipal casprincipal = assertion.getPrincipal();
            //从用户信息中取得用户名
            String usename = casprincipal.getName();
            //取出用户名之后需要将所有的相关信息(包括CAS相关信息)一起进行一个列表的创建
            List principal = CollectionUtils.asList(usename, casprincipal.getAttributes());
            //将信息和票根一起传入PrincipalCollection
            PrincipalCollection principalCollection = new SimplePrincipalCollection(principal, ticket);
        }catch (Exception e){
            e.printStackTrace();
        }
        return  super.doGetAuthenticationInfo(token);
    }
    //权限认证则与之前Shiro框架在ssm中相似
    public AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection){
        //1.从权限参数中取出用户名
        String eid= (String) principalCollection.getPrimaryPrincipal();
        //2.角色权限认证一般交由AuthorizationInfo的子类SimpleAuthorization进行处理
        SimpleAuthorizationInfo auth=new SimpleAuthorizationInfo();
        //3.取出根据登陆用户名查询出的角色权限信息
        Emp emp=new Emp();
        emp.setEid(eid);
        Map<String,Object> map=Service.findRoleAndActionByEmp(emp);
        Set<String> roles=(Set<String>) map.get("roles");
        Set<String> actions=(Set<String>) map.get("actions");
        //4.传入负责角色认证的类
        auth.setRoles(roles);
        auth.setStringPermissions(actions);
        //5.返回处理类对象
        return auth;
    }
}

5.环境配置

(1)在C:\Windows\System32\drivers\etc中配置本机地址簿,以便cas可以快速找到回调地址

在这里插入图片描述
(2)配置Spring的application.xml文件
核心代码

  <bean id="memberRealm" class="com.sheng.Realm.MemberRealm">
        <!--配置CAS服务器的地址-->
        <property name="casServerUrlPrefix" value="https://cas.com"/>
        <!--配置CAS服务器的回调服务器地址-->
        <property name="casService" value="http://127.0.0.1:8080/shiro-cas"/>
    </bean>

    <!--配置CAS访问过滤器-->
    <bean id="casFilter" class="org.apache.shiro.cas.CasFilter">
        <!--失败后访问的过滤器-->
        <property name="failureUrl" value="http://127.0.0.1:8080/travel-edit.jsp"/>
    </bean>

    <!--配置登陆注销过滤器-->
    <bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">
        <property name="redirectUrl" value="https://cas.com/loginout?service=http://127.0.0.1:8080/shiro-cas"/>
    </bean>
    <bean id="casSubjectFactory" class="org.apache.shiro.cas.CasSubjectFactory"></bean>
    <!--配置安全管理器-->
    <bean id="scurityManage" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!--配置你需要使用的Realms-->
        <property name="realm" ref="memberRealm"/>
        <property name="subjectFactory" ref="casSubjectFactory"/>
    </bean>


    <!--配置shiro过滤器-->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!--配置一个安全过滤器-->
        <property name="securityManager" ref="scurityManage"/>
        <!--认证成功后跳转的路径-->
        <property name="successUrl" value="/ListAll.action"/>
        <!--出现错误的时候跳转路径-->
        <property name="loginUrl" value="https://cas.com/login?service=http://127.0.0.1:8080/shiro-cas"/>
        <!--配置过滤器-->
        <property name="filters">
            <map>
                <entry key="login" value-ref="logoutFilter"/>
                <entry key="casFilter" value-ref="casFilter"/>
            </map>
        </property>
        <!--shiro里面需要针对所有的路径进行配置,所有的配置都要经过文本的形式设置
        本质上也就是shiro.ini中的[urls]-->
        <property name="filterChainDefinitions">
            <!--在此shiro过滤路径中,authc代表必须登陆才可以,rememberMe无效-->
            <!--user,代表只要登陆过,记住密码也可以-->
            <value>
                <!--你的票根返回路径必须使用casFilter-->
                /shiro-cas=casFilter
            </value>
        </property>
    </bean>

注意:shiro.com代表本机地址 /shiro-cas无实际意义,用以待会拦截使用,为什么要进行拦截呢?需要把票根拦截回CASRealm进行认证处理操作

大家看到这可能还有点糊涂,我在此处也十分糊涂,主要疑问在于,CAS服务器和CAS客户端是代表谁?CAS是如何和CAS进行数据传递的?下面在此再深入下CAS原理,
我认为CAS的原理本质上是一个JAVAWEB程序,依赖于tomcat,cas.war+tomcat形成了一个可执行验证的服务器,所有已被验证的用户信息都将被储存在这个服务器中,所有需要登陆的机器首先去询问CAS是否存在session信息,从而实现SSO单点登陆.

6.原理复现
CAS验证流程图
在这里插入图片描述
此图来源于网络

【第一步】终端第一次访问CAS—Client1,AuthenticationFilter会截获此请求:1、首先,检测本地Session没有缓存有用户信息;2、然后,检测到请求信息中没有ST;3、所以,CAS—Client1将请求重定向到CAS—Server,并传递 Service (也就是要访问的目的资源地址,以便登录成功过后转回该地址),例:https://cas/login?service=http:127.0.0.1:8080/

【第二步】终端第一次访问CAS—Server:1、CAS—Server检测到请求信息中没有TGC,所以跳转到自己的登录页;2、终端输入用户名、密码登录CAS—Server,认证成功后,CAS—Server会生成登录票据—TGT(集成了用户信息与ST),并随机生成一个服务票据—ST与CAS会话标识—TGC。TGT实际上就是Session,而TGC就是这标识这个Session存到Cookie中的SessionID;ST即,根据Service生成Ticket。3、然后,CAS—Server会将Ticket加在url 后面,然后将请求redirect 回客户web 应用,例如URL为http://127.0.0.1:8080/web1/?ticket=ST-5-Sx6eyvj7cPPCfn0pMZ

【第三步】这时,终端携带ticket再次请求CAS—Client1:1、这时客户端的AuthenticationFilter看到ticket 参数后,会跳过,由其后面的TicketValidationFilter 处理;2、TicketValidationFilter 会利用httpclient工具访问cas 服务的/serviceValidate 接口, 将ticket 、service 都传到此接口,由此接口验证ticket 的有效性,即向CAS—Server验证ST的有效性。3、TicketValidationFilter如果得到验证成功的消息,就会把用户信息写入web 应用的session里。至此为止,SSO 会话就建立起来了。

发布了30 篇原创文章 · 获赞 4 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_42549122/article/details/90318228