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

2018-09-17  本文已影响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
上一篇下一篇

猜你喜欢

热点阅读