zoukankan      html  css  js  c++  java
  • 单点登录CAS使用记(五):cas-client不拦截静态资源以及无需登录的请求。

    一.问题在哪?

    在配置cas-client中,有这么一段配置:

        <filter>
            <filter-name>CAS Filter</filter-name>
            <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
            <init-param>
                <param-name>casServerLoginUrl</param-name>
                <param-value>https://demo.testcas.com/cas/login</param-value>
            </init-param>
            <init-param>
                <param-name>serverName</param-name>
                <param-value>http://app1.testcas.com</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>CAS Filter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>

    详情请参考:单点登录CAS使用记(二):部署CAS服务器以及客户端

    意思大概是:拦截客户端的所有请求,如果发现还没有通过CAS认证中心认证,则强行重定向到Cas-server的登录页面。

    这里面有一个问题?

    即:客户端所有请求都被拦截并且跳转,包括静态资源,静态页面等,这是不合理的。

    二.如何解决?

    2.1 百度下大多数的解决方案

    扩展CASFilter过滤器,加上一个排除指定URL的功能,然后在web.xml配置中,手动添加需要排除的所有URL。

    这确是一种解决方法,但是过于繁琐,而且在网站请求地址过多的情况下,稍有不慎,就会出现遗漏。

    如果这是你想要的,请另行百度。

    2.2 我的解决方案:

    因为我是要整合两个比较成熟的项目,换言之,就是这两个项目已经自带了用户登录验证、用户权限验证、不拦截静态资源等处理。

    所以我是不是可以利用原有项目的拦截逻辑?

    原有项目功能简述:

    1.项目采用了SpringMVC框架

    2.对所有静态资源放行,例如:css、js、img等

    例如:web.xml中配置如下(激活Tomcat的defaultServlet来处理静态文件

    <servlet-mapping>  
      <servlet-name>default</servlet-name> 
      <url-pattern>*.jpg</url-pattern>   
    </servlet-mapping>  
    <servlet-mapping>    
      <servlet-name>default</servlet-name>
      <url-pattern>*.js</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
      <servlet-name>default</servlet-name>    
      <url-pattern>*.css</url-pattern>
    </servlet-mapping>

    3.自定义了一个@RequestSecurity的注解,并对所有有权限控制的方法加上该注解

    4.用户发出请求->被拦截器拦截->拦截器判断该用户请求方法是否被标注了@RequestSecurity

       IF:如果有该注解,继续判断用户是否已经登录(通过session是否存在来判断),如果没有登录,则重定向到登录页面进行登录。

       ELSE:如果没有该注解,证明该资源可随意访问,直接放行。

    注意上文红色描述,所以,我只要稍微改造一下原有项目的拦截器,让他不是直接跳转到原有登录页面,跳转到一个特定的请求地址,让cas-filter拦截只拦截这一个请求就可以了。

    三.改造验证

    第一步:修改原有项目拦截器

    项目中,有这么一段SpringMVC拦截器配置(伪代码展示)

        <mvc:interceptors>
            <bean class="com.xxxx.interceptor.SecurityInterceptor">
                <property name="redirectUrl">
                    <value>/login</value>
                </property>
           ...
            </bean>
        </mvc:interceptors>

    意思就是,一旦拦截到用户未登录,直接跳转到doLogin方法,让用户登录。

    我对他修改如下:

        <mvc:interceptors>
            <bean class="com.xxxx.interceptor.SecurityInterceptor">
                <property name="redirectUrl">
                    <value>/casLogin</value>
                </property>
           ...
            </bean>
        </mvc:interceptors>

    意思就是:一旦拦截到用户未登录,跳转到doCasLogin方法

    第二步:新增casLogin方法

        @RequestSecurity
        @RequestMapping(value = "casLogin", method = { RequestMethod.GET,
                RequestMethod.POST })
        public String casLogin()
        {
            return "welcome";
        }

    意思就是:如果用户未登录,会被强制重定向到本方法。

    第三步:修改cas-client的拦截器Cas-Filter的拦截范围

        <filter>
            <filter-name>CAS Filter</filter-name>
            <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
            <init-param>
                <param-name>casServerLoginUrl</param-name>
                <param-value>https://demo.testcas.com/cas/login</param-value>
            </init-param>
            <init-param>
                <param-name>serverName</param-name>
                <param-value>http://app1.testcas.com</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>CAS Filter</filter-name>
            <url-pattern>/casLogin</url-pattern>
        </filter-mapping>

    意思就是:CAS Filter只拦截casLogin请求,其他请求一律不拦截。一旦拦截到casLogin请求,说明用户暂未登录,则强制重定向到Cas-Server的登录页面。

    到这里,Cas-client不拦截静态资源处理就改造好了。

     

    但是,如果只做上面3步,进行测试的话,浏览器有可能会报“此页面包含重定向循环”的错误提示,并不能真正登入页面。

    原因看以下流程:

    1.首先被重定向到了Cas认证中心

    2.用户输入用户名密码等,点击登录通过了Cas登陆认证

    3.再一次被重定向回/casLogin,

    4.又被Cas-Fliter拦截,不过此时Cas-Fliter发现用户已经通过了Cas认证中心认证,不做重定向处理,继续后续处理。

    5.因为casLogin方法标注了@RequestSecurity,所以又被原有项目的mvc:interceptors拦截,拦截器发现用户未登录(通过session是否为空来判断)

    6.又被强行重定向会casLogin,然后又回到了4陷入了无穷的循环中...

    如何打破此重定向循环?

    关键在于第5步,当Cas-Server重定向回来时,会带回通过认证的用户信息。

    取得方式如下:

    AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal();
    String username = principal.getName();

    这时,在过滤器判断用户是否已经登录前,先行判断如果是Cas-server重定向过来的请求,并且principal、username存在,则把用户信息写入客户端UserSession中。

    然后再判断发现,已经写入了UserSession了,说明登录成功,直接登录welcome页面。

    登录成功。

    注:本文所记录的是自己摸索所得,并不敢完全保证程序逻辑的严谨性,如果您发现有所纰漏,请给予批评指正。


    单点登录CAS使用记系列:

  • 相关阅读:
    学了这些,你就算入门DIV+CSS了(转)
    【转】Web service是什么?
    [转]MongoDB插入和查询操作
    【转】安装m2e最佳方案
    XDS框架基本事务及其Soap消息实例
    数据表改变之后数据的迁移
    HL7 PID (Patient Identification) Segment(HL7规定的PID字段)
    海量数据库的设计
    【转】基于Axis2开发WebService
    【转】JAVA 调用Web Service的方法
  • 原文地址:https://www.cnblogs.com/notDog/p/5276632.html
Copyright © 2011-2022 走看看