基于 cas-client-core 的 普通 Java Web 项目 Cas 协议接入

cas-client-core 是 Cas 服务,官方提供的客户端 SDK,可快速的实现统一身份认证平台的集成!

第一步:引入依赖

在项目依赖管理中引入 cas-client-core 依赖 :

Maven 依赖
<!-- https://mvnrepository.com/artifact/org.jasig.cas.client/cas-client-core -->
<dependency>
    <groupId>org.jasig.cas.client</groupId>
    <artifactId>cas-client-core</artifactId>
    <version>3.6.4</version>
</dependency>
Gradle 依赖
// https://mvnrepository.com/artifact/org.jasig.cas.client/cas-client-core
implementation group: 'org.jasig.cas.client', name: 'cas-client-core', version: '3.6.4'

第二步:项目配置

修改用户是否登录的拦截器为cas拦截,具体配置如下

2.1 webapp 类型项目配置,修改web.xml,按照提示修改正确

<listener>
  <listener-class>
    org.jasig.cas.client.session.SingleSignOutHttpSessionListener
  </listener-class>
</listener>
<!--统一注销过滤器,最好配置在系统过滤器前面-->
<filter>
  <filter-name>CAS Single Sign Out Filter</filter-name>
  <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>CAS Single Sign Out Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
<!--认证过滤器配置开始-->
<filter>
  <filter-name>CAS Authentication Filter</filter-name>
  <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
  <!--修改正式的认证服务端地址-->
  <init-param>
    <param-name>casServerLoginUrl</param-name>
    <!--此处配置为认证真实地址-->
    <param-value>https://cas_server_url/login</param-value>
  </init-param>
  <!--修改客户端ip和端口-->
  <init-param>
    <param-name>serverName</param-name>
    <!--此处修改为应用服务器地址,http://ip:端口即可-->
    <param-value>http://ip:端口</param-value>
  </init-param>
  <init-param>
    <param-name>acceptAnyProxy</param-name>
    <param-value>true</param-value>
  </init-param>
</filter>

<filter>
  <filter-name>CAS Validation Filter</filter-name>
  <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
  <!--配置正式的认证服务端地址-->
  <init-param>
    <param-name>casServerUrlPrefix</param-name>
    <param-value>https://cas_server_url</param-value>
  </init-param>
  <!--修改客户端ip和端口-->
  <init-param>
    <param-name>serverName</param-name>
    <!--此处修改为应用服务器地址,http://ip:端口即可-->
    <param-value>http://ip:端口</param-value>
  </init-param>
</filter>

<filter>
  <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
  <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>

<filter>
  <filter-name>CAS Assertion Thread Local Filter</filter-name>
  <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
</filter>

<filter-mapping>
  <filter-name>CAS Validation Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
  <filter-name>CAS Authentication Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
  <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
  <filter-name>CAS Assertion Thread Local Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

<session-config>
  <tracking-mode>COOKIE</tracking-mode>
</session-config>
<!--认证过滤器配置结束-->

spring boot 项目配置 根据注释修改相应配置项

/**
* 客户端配置类
*/
public class CASProperty {
    /**
     * cas server 域名 https://cas_server_url
     */
    private String serverUrlPrefix;
    /**
     * cas server 登录地址 https://cas_server_url/login
     */
    private String serverLoginUrl;
    /**
     * 客户端首页地址 http://cas_client_url
     */
    private String clientHostUrl;
    /**
     * 客户端退出页 https://cas_server_url/logout?service=http://client.xxxxx.com/casLogin
     */
    private String clientLogoutUrl;
    /**
     * 不需要拦截的url前缀 /api/*|/auth/*
     */
    private String ignorePatternPath;
}
    @Bean
    public ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> singleSignOutHttpSessionListener() {
        ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> listener = new ServletListenerRegistrationBean<>();
        listener.setListener(new SingleSignOutHttpSessionListener());
        listener.setOrder(1);
        return listener;
    }

    /**
     * 该过滤器用于实现单点登出功能,单点退出配置,一定要放在其他filter之前
     * @return
     */
    @Bean
    public FilterRegistrationBean singleSignOutFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new SingleSignOutFilter());
        filterRegistration.addUrlPatterns("/*"); filterRegistration.addInitParameter("casServerUrlPrefix", casProperty.getServerUrlPrefix());
        filterRegistration.setOrder(3);
        return filterRegistration;
    }

    /**
     * 该过滤器负责用户的认证工作
     * @return
     */
    @Bean
    public FilterRegistrationBean authenticationFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new AuthenticationFilter());
        filterRegistration.addUrlPatterns("/*");
    //不需要拦截的url前缀
filterRegistration.addInitParameter("ignorePattern", casProperty.getIgnorePatternPath); filterRegistration.addInitParameter("casServerLoginUrl", casProperty.getServerLoginUrl()); filterRegistration.addInitParameter("serverName", casProperty.getClientHostUrl());
 filterRegistration.addInitParameter("useSession", "true"); filterRegistration.addInitParameter("redirectAfterValidation", "true");
        filterRegistration.setOrder(4);
        return filterRegistration;
    }

    /**
     * 该过滤器负责对Ticket的校验工作,使用CAS 3.0协议
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean cas30ProxyReceivingTicketValidationFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new Cas30ProxyReceivingTicketValidationFilter());
        filterRegistration.addUrlPatterns("/*");
        filterRegistration.addInitParameter("casServerUrlPrefix", casProperty.getServerUrlPrefix());
 filterRegistration.addInitParameter("serverName", casProperty.getClientHostUrl());
        filterRegistration.setOrder(5);
        return filterRegistration;
    }
    /**
     * 所有请求追加 request对象,和使用request.getRemoteUser()获取登录用户
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean httpServletRequestWrapperFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new HttpServletRequestWrapperFilter());
        filterRegistration.addUrlPatterns("/*");
        filterRegistration.setOrder(6);
        return filterRegistration;
    }

前后端分离的项目

后端服务配置同上,还需要增加中转接口,将前后端的会话id统一。以 spring boot + spring mvc + vue 项目为例增加中转接口,登录成功后跳转至前端首页,将后端jsessionid传递给前端。

    @GetMapping("/casLogin")
    @ApiOperation(value = "登录跳转页")
    public void login(HttpServletRequest request, HttpServletResponse response) throws IOException {
        HttpSession session = request.getSession();
        Assertion assertion = (Assertion) session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
        if (assertion != null) {
            String jsessionid = request.getSession().getId();
            response.sendRedirect(casProperty.getFrontUrl()+"?jsessionid="+jsessionid);
        }
    }
1 前端需要新增全局拦截器,未登录状态下一律拦截到casLogin接口,登录成功后会将会重定向至配置的前端页面,并追加面jsessionid参数,需要将jsessionid写入cookie,后续所有请求保持和后端jsessionid一致(注意跨域)
2 后端需要修改默认拦击器, CustomAuthenticationFilter 将未登录跳转登录页面的逻辑代码修改为返回401状态码,前端根据状态码,自行跳转页面登录
    @Bean
    public FilterRegistrationBean authenticationFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new CustomAuthenticationFilter());
        filterRegistration.addUrlPatterns("/*");
        filterRegistration.addInitParameter("ignorePattern", casProperty.getIgnorePatternPath());
        filterRegistration.addInitParameter("casServerLoginUrl", casProperty.getServerLoginUrl());
        filterRegistration.addInitParameter("serverName", casProperty.getClientHostUrl());
        filterRegistration.addInitParameter("useSession", "true");
        filterRegistration.addInitParameter("redirectAfterValidation", "true");
        filterRegistration.setOrder(4);
        return filterRegistration;
    }
class CustomAuthenticationFilter extends AbstractCasFilter
doFilter()

将此方法中的跳转逻辑修改为返回401状态码,供前端获取拦截

统一登出:

修改项目的退出方法为调用cas server的退出

    @ApiOperation(value = "退出系统")
    @GetMapping("casLogout")
    public String logout(HttpServletRequest request) {
        request.getSession().invalidate();
        return "redirect:"+casProperty.getClientLogoutUrl();
    }

登录状态下获取用户信息:

直接获取登录用户名

request.getRemoteUser();

获取详细用户信息

AttributePrincipal principal = (AttributePrincipal)request.getUserPrincipal();
Map attributes = principal.getAttributes();
Object moblie=attributes .get("moblie");
作者:杭州天音  创建时间:2022-07-23 17:59
最后编辑:杭州天音  更新时间:2025-08-22 15:44