美文网首页
CAS-5.3单点登录/退出客户端搭建(Springboot)

CAS-5.3单点登录/退出客户端搭建(Springboot)

作者: 那些流逝的岁月 | 来源:发表于2018-09-17 10:18 被阅读0次

    使用Springboot搭建cas客户端,主要是配置四个过滤器和一个监听器。

    单点登录

    创建过滤器类

    用于过滤不需要登录的用户,需要实现UrlPatternMatcherStrategy 接口,在matches 函数里添加不需要用户登录的链接。

    package com.zhang.springbootcasclient1.auth;
    
    import org.jasig.cas.client.authentication.UrlPatternMatcherStrategy;
    
    import java.util.regex.Pattern;
    
    /**
     * @Auther: zhang
     * @Date: 2018/8/30 09:46
     * @Description:过滤掉不需要授权登录的页面
     */
    public class SimpleUrlPatternMatcherStrategy implements UrlPatternMatcherStrategy{
        private Pattern pattern;
        /**
         * description:判断是否匹配这个字符串
         * @param: [url]用户请求的连接
         * @return: true:不需要拦截
         *          false:必须要登录
         */
        @Override
        public boolean matches(String url) {
            //使用正则表达式来匹配需要忽略的连接
            return this.pattern.matcher(url).find();
        }
    
        /**
         * description:正则表达式的规则,该规则在配置AuthenticationFilter的ignorePattern中设置
         * @param: [pattern]
         * @return: void
         */
        @Override
        public void setPattern(String pattern) {
            this.pattern = Pattern.compile(pattern);
        }
    }
    

    创建首页控制器

    package com.zhang.springbootcasclient1.controller;
    
    import org.jasig.cas.client.authentication.AttributePrincipal;
    import org.jasig.cas.client.util.AbstractCasFilter;
    import org.jasig.cas.client.validation.Assertion;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import javax.servlet.http.HttpServletRequest;
    import java.security.Principal;
    import java.util.Map;
    
    /**
     * @Auther: zhangll
     * @Date: 2018/8/30 10:11
     * @Description:
     */
    @Controller
    public class IndexController {
        @RequestMapping(value={"/", "/index"})
        public String index(HttpServletRequest request) {
    
            //获取cas给我们传递回来的对象,这个对象在Session中
            //session的 key是 CONST_CAS_ASSERTION
            Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
    
            Principal principal  = assertion.getPrincipal();
    
            String loginName =principal.getName();
            System.out.printf("登录用户名:%s\r\n",loginName);
    
            System.out.printf("ValidFromDate:%s\r\n",assertion.getValidFromDate());
            System.out.printf("ValidUntilDate:%s\r\n",assertion.getValidUntilDate());
            System.out.printf("AuthenticationDate:%s\r\n",assertion.getAuthenticationDate());
    
            //获取自定义返回值的数据
            if (principal instanceof AttributePrincipal) {
                //cas传递过来的数据
                Map<String,Object> result =( (AttributePrincipal)principal).getAttributes();
                for(Map.Entry<String, Object> entry :result.entrySet()) {
                    String key = entry.getKey();
                    Object val = entry.getValue();
                    System.out.printf("%s:%s\r\n",key,val);
                }
            }
    
            return "index";
        }
    }
    

    首页代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>当前所在子系统:测试系统1</h1>
    <h2><a href="http://springbootcasclient.com:8001/">系统1</a></h2>
    <h2><a href="http://springbootcasclient.com:8002/">系统2</a></h2>
    <b>Authenticated User Id:</b> <a href="logout.jsp" title="Click here to log out" th:text="${#request.remoteUser}"/>
    <br/>
    <a th:href="${#request.contextPath}+'/logoutDefault'" title="Click here to log out">退出系统(默认退出页面)</a>
    <a th:href="${#request.contextPath}+'/logoutCustom'" title="Click here to log out">退出系统(定制退出页面)</a>
    </body>
    </html>
    

    用户退出控制器

    package com.zhang.springbootcasclient1.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import javax.servlet.http.HttpSession;
    
    /**
     * @Auther: zhangll
     * @Date: 2018/8/30 11:35
     * @Description:
     */
    @Controller
    public class LogoutController {
        @RequestMapping("/logoutDefault")
        public String logout1(HttpSession session) {
            session.invalidate();
    
            // 直接退出,走默认退出方式
            return "redirect:https://casserver.com:8443/logout";
        }
    
        @RequestMapping("/logoutCustom")
        public String logout2(HttpSession session) {
            session.invalidate();
            // 退出登录后,跳转到退出成功的页面,不走默认页面
            return "redirect:https://casserver.com:8443/logout?service=http://springbootcasclient.com:8001/logout/success";
        }
    
        @RequestMapping("/logout/success")
        @ResponseBody
        public String logout2() {
            return "系统1注销成功";
        }
    }
    

    配置过滤器到springboot

    package com.zhang.springbootcasclient1;
    
    import org.jasig.cas.client.authentication.AuthenticationFilter;
    import org.jasig.cas.client.session.SingleSignOutFilter;
    import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
    import org.jasig.cas.client.util.HttpServletRequestWrapperFilter;
    import org.jasig.cas.client.validation.Cas30ProxyReceivingTicketValidationFilter;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
    import org.springframework.context.annotation.Bean;
    
    import java.util.EventListener;
    import java.util.HashMap;
    import java.util.Map;
    
    @SpringBootApplication
    public class SpringbootCasClient1Application {
        private static final String CAS_SERVER_URL_PREFIX = "https://casserver.com:8443/";
        private static final String CAS_SERVER_URL_LOGIN = "https://casserver.com:8443/login";
    
        //本机的名称
        private static final String SERVER_NAME = "http://springbootcasclient.com:8001/";
    
        /**
         * description: 登录过滤器
         * @param: []
         * @return: org.springframework.boot.web.servlet.FilterRegistrationBean
         */
        @Bean
        public FilterRegistrationBean filterSingleRegistration() {
            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setFilter(new SingleSignOutFilter());
            // 设定匹配的路径
            registration.addUrlPatterns("/*");
            Map<String,String> initParameters = new HashMap<String, String>();
            initParameters.put("casServerUrlPrefix", CAS_SERVER_URL_PREFIX);
            registration.setInitParameters(initParameters);
            // 设定加载的顺序
            registration.setOrder(1);
            return registration;
        }
    
    
        /**
         * description:过滤验证器
         *     * @param: []
         * @return: org.springframework.boot.web.servlet.FilterRegistrationBean
         */
        @Bean
        public FilterRegistrationBean filterValidationRegistration() {
            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setFilter(new Cas30ProxyReceivingTicketValidationFilter());
            // 设定匹配的路径
            registration.addUrlPatterns("/*");
            Map<String,String>  initParameters = new HashMap<String, String>();
            initParameters.put("casServerUrlPrefix", CAS_SERVER_URL_PREFIX);
            initParameters.put("serverName", SERVER_NAME);
            initParameters.put("useSession", "true");
            registration.setInitParameters(initParameters);
            // 设定加载的顺序
            registration.setOrder(1);
            return registration;
        }
    
    
        /**
         * description:授权过滤器
         * @param: []
         * @return: org.springframework.boot.web.servlet.FilterRegistrationBean
         */
        @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", CAS_SERVER_URL_LOGIN);
            initParameters.put("serverName", SERVER_NAME);
            //忽略/logout的路径
            initParameters.put("ignorePattern", "/logout/*");
            initParameters.put("ignoreUrlPatternType", "com.zhang.springbootcasclient1.auth.SimpleUrlPatternMatcherStrategy");
    
            registration.setInitParameters(initParameters);
            // 设定加载的顺序
            registration.setOrder(1);
            return registration;
        }
    
        /**
         * wraper过滤器
         * @return
         */
        @Bean
        public FilterRegistrationBean filterWrapperRegistration() {
            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setFilter(new HttpServletRequestWrapperFilter());
            // 设定匹配的路径
            registration.addUrlPatterns("/*");
            // 设定加载的顺序
            registration.setOrder(1);
            return registration;
        }
    
        /**
         * 添加监听器
         * @return
         */
        @Bean
        public ServletListenerRegistrationBean<EventListener> singleSignOutListenerRegistration(){
            ServletListenerRegistrationBean<EventListener> registrationBean = new ServletListenerRegistrationBean<EventListener>();
            registrationBean.setListener(new SingleSignOutHttpSessionListener());
            registrationBean.setOrder(1);
            return registrationBean;
        }
    
        public static void main(String[] args) {
            SpringApplication.run(SpringbootCasClient1Application.class, args);
        }
    }
    

    application.properties

    logging.file=logs/config/springboot-cas-client1.log
    info.name=springboot-cas-client1
    
    server.port=8001
    

    pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.zhang</groupId>
        <artifactId>springboot-cas-client</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <name>springboot-cas-client</name>
        <description>Demo project for Spring Boot CAS Client</description>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.4.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
            <java.cas.client.version>3.5.0</java.cas.client.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--cas客户端 -->
            <dependency>
                <groupId>org.jasig.cas.client</groupId>
                <artifactId>cas-client-core</artifactId>
                <version>${java.cas.client.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    

    登录测试

    按照同样的方法实现客户端系统2。
    启动cas服务器端和两个客户端。输入http://springbootcasclient.com:8001/,则跳转到登录界面

    client1_login.png
    输入用户名和密码(casuser/Mellon),则进入客户端系统1的index页面。
    client1-index.png
    输入http://springbootcasclient.com:8002/,直接跳转到客户端系统2的index页面,不需要再重新登录。
    client2-index.png

    单点退出

    单点退出,需要下面三个步骤:1、添加过滤器类,过滤掉不需要登录的url;2、添加退出跳转的控制器;3、修改服务端application.properties ,加cas.logout.followServiceRedirects=true,让客户端可以自己制定退出的路径,否则会走默认退出路径。

    添加过滤器类

    过滤器类需要实现UrlPatternMatcherStrategy接口,然后配置到springboot中,请参考单点登录创建过滤器类配置过滤器到springboot

    添加退出控制器

    退出的方式有两种,一种是走默认的路径,另一种是走自定义的返回路径。请参考单点登录用户退出控制器

    修改服务端application.properties

    cas.logout.followServiceRedirects=true
    

    将上面的内容添加到applicaiton.properties, 这样就可以允许客户端定制自己的退出路径了。

    注意问题

    http协议配置:cas 5.3.x默认客户端不支持http协议, 如果不进行配置,则会出现“未认证授权的服务”错误。


    unauthorized-service-error.png

    要配置兼容http协议,需要在HTTPSandIMAPS-10000001.json文件中添加http。


    HTTPSandIMAPS-10000001.png
    同时需要在application.properties中添加
    cas.serviceRegistry.initFromJson=true
    

    相关文章

      网友评论

          本文标题:CAS-5.3单点登录/退出客户端搭建(Springboot)

          本文链接:https://www.haomeiwen.com/subject/lshrwftx.html