CAS单点登录:服务端5.3,springboot集成客户端

一、准备

jdk版本最低要求1.8

服务端使用cas-overlay-template,版本是5.3,下载地址,下载解压完成后,作为maven项目导入idea,如图所示:
项目结构

不需要任何开发,执行maven package命令,即可打包生成cas.war文件,放在tomcat的wenapps下,直接启动,或者直接在idea中配置tomcat启动,启动完成之后,可以看到登录页。

客户端使用springboot集成CAS,创建springboot项目。我这里使用的是2.2.2.RELEASE版本

二、配置

服务端使用的是overlay项目,可以通过创建同名文件,来覆盖模板的文件,从而达到自定义开发服务端的目的。
注意:这里的同名文件,指的是编译之后的全路径相同,名称相同。比如,我在项目中创建一个src的目录,在这个目录下,有一个spring.factories的文件,编译时,我的文件会覆盖的同路径下的spring.factories同名文件,使用的是我的文件,而不是模板中的文件。
如果想服务端支持https,请看这位大佬
如果不使用http,可以在按照上面的方法创建一个services目录下的HTTPSandIMAPS-10000001.json的同名文件,从编译之后的WEB-INF/services目录下,全部复制到新建的文件中,如下图所示,在箭头所指位置添加 http 字符串,记得添加 | 符号。

复制模板文件application.properties,到src中,修改端口号,并插入以下两行配置,即可支持http访问。

cas.tgc.secure=false
cas.serviceRegistry.initFromJson=true

客户端配置文件如下:
pom.xml依赖

<!--CAS客户端集成-->
<dependency>
     <groupId>net.unicon.cas</groupId>
     <artifactId>cas-client-autoconfig-support</artifactId>
     <version>1.5.0-GA</version>
 </dependency>

application.yml

cas:
  server-url-prefix: http://localhost:8080/cas  #CAS项目地址
  server-login-url: ${cas.server-url-prefix}/login  #CAS登录地址
  client-host-url: http://localhost  #本项目地址
  validation-type: cas   #cas,cas3,SAML三种选择

validation-type这个属性,除开SAML不说,要想在获取到自定义信息(这个得修改服务端,自定义返回消息handler,还是看这位大佬,以及之后如何把自定义的handler注册到服务端中,还是看这位),必须是cas3(不配置默认是CAS3),才能返回attributes信息。如果是cas,只能返回当前用户名。
在这里插入图片描述
过滤器配置

package cn.he.develop.config;

import com.alibaba.fastjson.JSONObject;
import net.unicon.cas.client.configuration.CasClientConfigurerAdapter;
import net.unicon.cas.client.configuration.EnableCasClient;
import org.jasig.cas.client.authentication.AttributePrincipal;
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.AbstractCasFilter;
import org.jasig.cas.client.util.HttpServletRequestWrapperFilter;
import org.jasig.cas.client.validation.Assertion;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.security.Principal;
import java.util.Map;

@Configuration
@Controller
@EnableCasClient
public class CasConfig extends CasClientConfigurerAdapter {

    @Value("${cas.server-url-prefix}")
    private String CAS_URL;

    @Value("${cas.client-host-url}")
    private String APP_URL;

    @Override
    public void configureAuthenticationFilter(FilterRegistrationBean authenticationFilter) {
        super.configureAuthenticationFilter(authenticationFilter);
        //authenticationFilter.getInitParameters().put("authenticationRedirectStrategyClass","com.patterncat.CustomAuthRedirectStrategy");
    }


    @Bean
    public ServletListenerRegistrationBean servletListenerRegistrationBean(){
        ServletListenerRegistrationBean  listenerRegistrationBean = new ServletListenerRegistrationBean();
        listenerRegistrationBean.setListener(new SingleSignOutHttpSessionListener());
        listenerRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return listenerRegistrationBean;
    }

    /**
     * 单点登录退出
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean singleSignOutFilter() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new SingleSignOutFilter());
        registrationBean.addUrlPatterns("/*");
        registrationBean.addInitParameter("casServerUrlPrefix", CAS_URL);
        registrationBean.setName("CAS Single Sign Out Filter");
        registrationBean.setOrder(1);
        return registrationBean;
    }

    /**
     * 单点登录认证
     * @return
     */
    @Bean
    public FilterRegistrationBean AuthenticationFilter() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new AuthenticationFilter());
        registrationBean.addUrlPatterns("/*");
        registrationBean.setName("CAS Filter");
        registrationBean.addInitParameter("casServerLoginUrl", CAS_URL);
        registrationBean.addInitParameter("serverName", APP_URL);
        registrationBean.setOrder(3);
        return registrationBean;
    }

    /**
     * 单点登录请求包装
     * @return
     */
    @Bean
    public FilterRegistrationBean httpServletRequestWrapperFilter(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new HttpServletRequestWrapperFilter());
        registrationBean.addUrlPatterns("/*");
        registrationBean.setName("CAS HttpServletRequest Wrapper Filter");
        registrationBean.setOrder(5);
        return registrationBean;
    }
    
    //登出
    @RequestMapping("/logout")
    public String logout(HttpSession session){
        session.invalidate();
        return "redirect:"+CAS_URL+"/logout?service="+APP_URL+"/admin/index.html";
    }
    /**
     * 从kweb-cas中获取登录信息
     * @param request
     * @return
     */
    @GetMapping(value = {"/loginUserInfo"})
    @ResponseBody
    public String loginUserInfo(HttpServletRequest request){
        Assertion assertion = (Assertion) request.getSession().getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
        if(assertion!= null){
            AttributePrincipal principal = assertion.getPrincipal();
            String s = JSONObject.toJSONString(assertion);
            //获取自定义返回值的数据
            Principal principal2  = (AttributePrincipal) request.getUserPrincipal();
            if (request.getUserPrincipal() != null) {

                if (principal2 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 s;
        }else {
            return null;
        }
    }


}

至此,项目配置完成。

三、遇到的问题

1.无法返回自定义attributes信息

validation-type: cas,配置了cas。
cas的登录流程是登录之后,拿到ticket,然后再去验证ticket是否正确,正确则返回认证信息。在cas的jar包中,Cas30ProxyReceivingTicketValidationFilter,Cas20ProxyReceivingTicketValidationFilter,这两个类中的Cas30ServiceTicketValidator,Cas20ServiceTicketValidator是用来验证ticket的。 Cas20ServiceTicketValidator中配置的验证url前缀是“serviceValidate”,而Cas30ProxyReceivingTicketValidationFilter中配置的验证url前缀是“p3/serviceValidate”,配置的过滤器不同,验证的url也就不同,加上的p3的前缀,服务端会认为是使用3.0协议,会返回自定义的消息,就是attributes中的消息

在这里插入图片描述
在这里插入图片描述

2.服务端无法使用自己的文件,编译之后还是使用模板的代码

文件的覆盖,一定是要同路径同名称的,也就是编译之后的路径名称相同,自己写的文件,会覆盖掉模板中的文件

3.在过滤器中自己配置了Cas30ProxyReceivingTicketValidationFilter,没有生效

模板会根据你的配置,默认注册一个Cas30ProxyReceivingTicketValidationFilter或者是Cas20ProxyReceivingTicketValidationFilter,这个filter的优先级比你自己配置的高,执行到这个filter,就不会执行到后边自己配置的。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值