zoukankan      html  css  js  c++  java
  • cas 3.5.3服务器搭建+spring boot集成+shiro模拟登录(不修改现有shiro认证架构)

    因为现有系统外部接入需要,需要支持三方单点登录。由于系统本身已经是微服务架构,由多个业务独立的子系统组成,所以有自己的用户认证微服务(不是cas,我们基础设施已经够多了,现在能不增加就不增加)。但是因为客户和其他接入(公有云网络)原因,无法通过token+redis实现,所以还需要支持外部的cas。

    现有认证系统采用shiro实现,业务子系统采用shiro+token假登录实现。现在要支持通过配置设置系统自身的认证子系统是否启用三方cas登录。这样无论是使用自己的认证实现、还是三方CAS,整体流程就完全一样。

    CAS服务器搭建

    从cas 4开始,官方就已经不再提供release war,转而需要自行下载源码打包,网上很多,这里不再阐述(下载依赖有点慢)。4.x以及之前的war可以从https://mvnrepository.com/artifact/org.jasig.cas/cas-server-webapp下载。下载后,解压到tomcat webapp目录:

    启动:

    修改下列配置:

    去除https认证:

    在tomcatwebappscasWEB-INFdeployerConfigContext.xml文件
          的p:httpClient-ref="httpClient"后面添加p:requireSecure="false" 
    把tomcatwebappscasWEB-INFspring-configuration的
          ticketGrantingTicketCookieGenerator.xml文件里面把p:cookieSecure="true"改为false;
          p:cookieMaxAge="-1"改为3600(-1是不保存cookie,3600秒是一个小时,保存登录信息)
    把tomcatwebappscasWEB-INFspring-configuration的
          warnCookieGenerator.xml的p:cookieSecure="true"改为false
          p:cookieMaxAge="-1"改为3600

     配置单点登出: 

      将tomcatwebappscasWEB-INFcas-servlet.xml中${cas.logout.followServiceRedirects:false}括号里的值改为true

    可以配置简单测试认证(去掉<bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />注释)或基于数据源认证(可以参考https://www.cnblogs.com/wlwl/p/10056067.html)。

    spring boot cas客户端集成

    库依赖:

            <dependency>
                <groupId>net.unicon.cas</groupId>
                <artifactId>cas-client-autoconfig-support</artifactId>
                <version>1.5.0-GA</version>
            </dependency>
            <dependency>
                <groupId>org.jasig.cas.client</groupId>
                <artifactId>cas-client-core</artifactId>
                <version>3.2.1</version>
                <exclusions>
                    <exclusion>
                        <artifactId>servlet-api</artifactId>
                        <groupId>javax.servlet</groupId>
                    </exclusion>
                </exclusions>
            </dependency>

    application.properties中加上下列配置:

    cas.server-url-prefix=http://localhost:8080/cas
    cas.server-login-url=http://localhost:8080/cas/login
    cas.client-host-url=http://localhost:18080/
    cas.use-session=true
    cas.validation-type=cas
    casClientLogoutUrl=http://localhost:8080/cas/logout?service=http://localhost:18080/tabase/logout.html
    import net.unicon.cas.client.configuration.EnableCasClient;
    
    @EnableCasClient //启用cas client
    @CloudApplication
    public class ConsumerStarter {
        public static void main(String[] args) {
            CloudBootstrap.run(ConsumerStarter.class, args);
        }
    }
    
    package com.hs;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import org.jasig.cas.client.authentication.AuthenticationFilter;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class CASAutoConfig {
        @Value("${cas.server-url-prefix}")
        private String serverUrlPrefix;
        @Value("${cas.server-login-url}")
        private String serverLoginUrl;
        @Value("${cas.client-host-url}")
        private String clientHostUrl;
     
        /**
         * 授权过滤器
         * @return
         */
        @Bean
        public FilterRegistrationBean filterAuthenticationRegistration() {
            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setFilter(new AuthenticationFilter());
            // 设定匹配的路径
            registration.addUrlPatterns("/*");
            Map<String,String> initParameters = new HashMap<String, String>();
            initParameters.put("casServerLoginUrl", serverUrlPrefix);
            initParameters.put("serverName", clientHostUrl);
            //忽略的url,"|"分隔多个url
            initParameters.put("ignorePattern", "/logout/success|/index");
            registration.setInitParameters(initParameters);
            // 设定加载的顺序
            registration.setOrder(1);
            return registration;
        }
    }

    shiro模拟登录(不修改现有shiro认证架构)

    cas登录成功后,会给应用返回ticket,其中包含了用户名。此时应用主页会被shiro过滤器UserFilter拦截,在其中可以判断HttpServletRequest上是否有ticket的用户名,有、且为有效用户名,就可以用该用户名模拟登录了。这样整个shiro认证流程几乎没有变化,也不需要修改FormAuthenticationFilter。

    cas在2.x和3.x版本获取用户名不一样,这一点需要注意。

    2.x版本client获取CAS传递过来的用户名的方法:

    // 以下三者都可以
    session.getAttribute(CASFilter.CAS_FILTER_USER);
    session.getAttribute("edu.yale.its.tp.cas.client.filter.user");
    
    CASFilterRequestWrapper  reqWrapper=new CASFilterRequestWrapper(request);
    reqWrapper.getRemoteUser());

    3.x版本client获取CAS传递过来的用户名的方法:

    HttpServletRequest request = ServletActionContext.getRequest();   
    AttributePrincipal principal = (AttributePrincipal)request.getUserPrincipal();   
    String username = principal.getName();   
    Long orgnId = Long.parseLong(principal.getAttributes().get("orgnId").toString());  

    拿到后,就可以模拟登陆了。

            boolean isAllowed = super.isAccessAllowed(request, response, mappedValue);
            //
            if (isAllowed) {
    
            } else if (Boolean.valueOf(BaseConfig.getConfig("ta.casEnable","false"))) {
                AttributePrincipal principal = (AttributePrincipal)((HttpServletRequest) request).getUserPrincipal();
                String username = principal.getName();
                Subject subject = getSubject(request, response);
                AuthenticationToken token = new UsernamePasswordToken();
                ((UsernamePasswordToken) token).setUsername(username);
                ((UsernamePasswordToken) token).setPassword(new char[] {'1'});
                subject.login(token);
                isAllowed = super.isAccessAllowed(request, response, mappedValue);
            }

    shiro登出

    在shiro的logoutFilter中调用session.invalidate()即可。然后返回casClientLogoutUrl配置的地址退出cas即可。

            /**
             * CAS添加开始
             */
            if (StringUtils.isNotBlank(BaseConfig.getConfig("casClientLogoutUrl"))) {
                ((HttpServletRequest)request).getSession().invalidate();
                redirectUrl = BaseConfig.getConfig("casClientLogoutUrl");
            }
            // CAS添加结束
            return redirectUrl;

    此致,就完整的实现了cas+shiro模拟登录。

    CAS ticket过期策略,参考:https://www.cnblogs.com/gao241/p/3367869.html

    CAS流程介绍,参考:https://www.cnblogs.com/xiatian0721/p/8136305.html

    CAS官方架构参考:https://apereo.github.io/cas/5.3.x/planning/Architecture.html

  • 相关阅读:
    java线程安全单例
    ConcurrentHashMap 中putIfAbsent 和put的区别
    Google Guava -缓存cache简单使用
    Jstorm TimeCacheMap源代码分析
    poj 3277...离散化+线段树...
    spoj 1716...动态区间的最大连续子段和问题...点修改...
    spark
    hdu 1754...忘了个getchar(),蛋疼了半天...原来划水也有蛋疼的时候...
    hdu 1556...线段树划水...
    PHP学习笔记06——面向对象版图形计算器
  • 原文地址:https://www.cnblogs.com/zhjh256/p/11489001.html
Copyright © 2011-2022 走看看