CAS认证及代理访问举例

CAS-认证流程详解 基础知识 名词解释 AS Authentication Service:认证服务,发放TGT KDC Key Distribution Center:密钥发放中心 TGS Ticket-Granting Service:票据授权服务,索取TGT,发放ST TGC ticket-granting cookie:授权的票据证明,由CAS Server通过SSL方式发送给终端用户。该值存在Cookie中,根据TGC可以找到TGT。 TGT Ticket Granting tieckt:俗称大令牌,或者票根,由KD 阅读详情

一、 CAS简介

Cas的全称是Centeral Authentication Service,是对单点登录SSO(Single Sign On)
的一种实现。其由Cas Server和Cas Client两部分组成,Cas Server是核心,而Cas Client通常就对应于我们的应用。一个Cas Server可以对应于多个Cas Client。它允许我们在一个Client进行登录以后无需再让用户输入用户名和密码进行认证即可访问其它Client应用。

Cas Server的主要作用是通过发行和验证Ticket(票)来对用户进行认证和授权访问Client应用,用于认证的凭证信息都是由Cas Server管理的。而Cas Client就对应于我们真正的应用,当然其中会使用到Cas相关的类,用于与Cas Server进行交互。

二、 CAS认证流程

下图是官网上用户认证的流程图
官网流程图

用户首次访问应用app1

如你所见,在第一次访问应用app1时,由于没有登录会直接跳转到Cas Server去进行登录认证,此时将附带查询参数service在Cas Server的登录地址上,表示登录成功后将要跳转的地址。
此时Cas Server检查到没有之前成功登录后生成的SSO Session信息,那么就会引导用户到登录页面进行登录。如:

https://cas.example.com:8443/cas/login?service=http%3A%2F%2Fapp.example.com%3A8080%2Flogin%2Fcas

用户输入信息提交登录请求,Cas Server认证成功后将生成对应的SSO Session,以及名为CASTGC的cookie,该cookie包含用来确定用户SSO Session的Ticket Granting Ticket(TGT)。之后会生成一个Service Ticket(ST),并将以ticket作为查询参数名,以该ST作为查询参数值跳转到登录时service对应的URL。如:

http://app.example.com:8080/login/cas?ticket=ST-7-hXaLlWKHnwc-RpxHEyVf0aQVF0wxxxxxx

之后的操作对用户来说都是透明的,即不可见的。
app1之后将以service和ticket作为查询参数请求Cas Server对service进行验证,地址举例:

https://cas.example.com:8443/cas/p3/serviceValidate?ticket=ST-15-K7SRE776Y1e4LtJqcMOzzaehcbgmaruilei&service=http%3A%2F%2Fapp.example.com%3A8080%2Flogin%2Fcas

验证通过后Cas Server将返回当前用户的用户名等信息。app1就会给当前用户生成其自身的Session,以后该用户以该Session都可以成功的访问app1,而不需要再去请求Cas Server进行认证。流程图如下

第二次访问app1

当该用户再去访问app2的时候,由于其在app2上没有对应的Session信息,将会跳转到Cas Server的登录地址,Cas Server此时发现其包含名为CASTGC的cookie,将获取其中包含的TGT来获取对应的SSO Session,然后会将用户重定向到app2对应的地址,以Service Ticket作为查询参数。之后app2会向Cas Server发送请求校验该Service Ticket,校验成功后app2将建立该用户对应的Session信息,以后该用户以该Session就可以自由的访问app2了。

综上所述,我们知道,各系统之间的单点登录是通过Cas Server生成的SSO Session来交流的,而用户与实际的应用系统进行交互的时候,各应用系统将建立单独的Session,以满足用户与该系统的交互需求。

三、 接入CAS所需配置

pom.xml引入文件配置
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-cas</artifactId>
    <version>5.1.5.RELEASE</version>
</dependency>
application.yml配置
cas:
  server:
    prefix: https://cas.example.com:8443/cas
    login: /login
    logout: /logout
  client:
    prefix: http://127.0.0.1:8080/clientapp
    login: /login/cas
    logout: /logout/cas
cas相关过滤器、入口配置
@Configuration
public class CasSecurityProperties {
    @Value("${cas.server.prefix}")
    private String casServerPrefix;

    @Value("${cas.server.login}")
    private String casServerLogin;

    @Value("${cas.server.logout}")
    private String casServerLogout;

    @Value("${cas.client.prefix}")
    private String casClientPrefix;

    @Value("${cas.client.login}")
    private String casClientLogin;

    @Value("${cas.client.logout}")
    private String casClientLogout;
    
    /**
     * 设置本cas服务的属性bean
     * serviceProperties.setAuthenticateAllArtifacts(true);
     * 设置带有ticket参数的请求都可以触发认证,主要在代理认证时使用
     * @return
     */
    @Bean
    public ServiceProperties serviceProperties() {
        ServiceProperties serviceProperties = new ServiceProperties();
        serviceProperties.setService(casClientPrefix + casClientLogin);
        serviceProperties.setAuthenticateAllArtifacts(true);
        return serviceProperties;
    }

    /**
     * 票据验证,使用cas3.0 代理票据认证器
     * 传递cas server地址进行初始化
     */
    @Bean
    public Cas30ProxyTicketValidator ticketValidator() {
        Cas30ProxyTicketValidator validator = new Cas30ProxyTicketValidator(casServerPrefix);
        return validator;
    }

    /**
     * 接收cas服务器发出的注销请求
     */
    @Bean
    public SingleSignOutFilter singleSignOutFilter() {
        SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
        singleSignOutFilter.setCasServerUrlPrefix(casServerPrefix);
        singleSignOutFilter.setIgnoreInitConfiguration(true);
        return singleSignOutFilter;
    }

    @Bean
    public LogoutSuccessHandler logoutSuccessHandler() {
        return new MyLogoutSuccessHandler();
    }

    /**
     * 注销请求转发到cas server
     * 由于登出会重定向到cas server页面,发生跨域,
     * 此处重写了LogoutSuccessHandler,后台只进行session销毁,然后通知前端进行登出跳转
     */
    @Bean
    public LogoutFilter logoutFilter(LogoutSuccessHandler logoutSuccessHandler) {
        LogoutFilter logoutFilter = new LogoutFilter(logoutSuccessHandler, new SecurityContextLogoutHandler());
        logoutFilter.setFilterProcessesUrl(casClientLogout);
        return logoutFilter;
    }

    @Bean
    public UserDetailsService userDetailsService() {
        UserServiceImpl userService = new UserServiceImpl();
        return userService;
    }

    @Bean
    public CasAuthenticationProvider casAuthenticationProvider(ServiceProperties sp, TicketValidator ticketValidator, UserDetailsService userDetailsService) {
        CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
        casAuthenticationProvider.setKey("casProvider");
        casAuthenticationProvider.setServiceProperties(sp);
        casAuthenticationProvider.setTicketValidator(ticketValidator);
        casAuthenticationProvider.setUserDetailsService(userDetailsService);
        return casAuthenticationProvider;
    }

    /**
     * cas filter类,针对/login/cas请求做用户认证
     * filter.setAuthenticationDetailsSource(new ServiceAuthenticationDetailsSource(serviceProperties));
     * 该设置可以在认证信息中记录请求原始url,不再使用spring security默认的 /login/cas
     *
     * @param serviceProperties
     * @param provider
     * @return
     */
    @Bean
    public CasAuthenticationFilter casAuthenticationFilter(ServiceProperties serviceProperties,
                                                           AuthenticationProvider provider) {
        CasAuthenticationFilter filter = new CasAuthenticationFilter();
        filter.setServiceProperties(serviceProperties); 
        filter.setAuthenticationManager(new ProviderManager(Arrays.asList(provider)));
        return filter;
    }

    /**
     * filter入口,未登录时跳转到cas server
     * @param serviceProperties
     * @return
     */
    @Bean
    @Primary
    public CasAuthenticationEntryPoint authenticationEntryPoint(ServiceProperties serviceProperties) {
        CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint();
        entryPoint.setLoginUrl(casServerPrefix + casServerLogin);
        entryPoint.setServiceProperties(serviceProperties);
        return entryPoint;
    }

其中UserDetailsServiceImpl是需要用户自己实现的类,可以在其中给登录用户配置权限角色相关信息,实现举例:

public class UserServiceImpl implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
     {
        List<GrantedAuthority> authorities = new ArrayList<>();
        //去数据库查询用户 及相关权限
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
        return new User(username, "N/A", true, true, true, true, authorities);
    }
}
总入口配置
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private AuthenticationProvider authenticationProvider;

    @Resource
    private CasAuthenticationFilter casAuthenticationFilter;

    @Resource
    private AuthenticationEntryPoint authenticationEntryPoint;

    @Resource
    private LogoutFilter logoutFilter;

    @Resource
    private SingleSignOutFilter singleSignOutFilter;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProvider);
    }

    /**
     * 配置放行的资源
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js/**", "/fonts/**", "/css/**", "/favicon.ico","/test.html");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .headers().frameOptions().disable()
                .and()
                .authorizeRequests()
                .anyRequest().authenticated().and()
                .logout().permitAll()
                .and()
                .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
                .and()
                .addFilter(casAuthenticationFilter)
                .addFilterBefore(singleSignOutFilter, CasAuthenticationFilter.class)
                .addFilterBefore(logoutFilter, LogoutFilter.class);
    }

四、 CAS代理认证(CAS Proxy)

考虑这样一种场景:有两个应用App1和App2,它们都是受Cas Server保护的,即请求它们时都需要通过Cas Server的认证。现需要在App1中通过Http请求访问App2,显然该请求将会被App2配置的Cas的AuthenticationFilter拦截并转向Cas Server,Cas Server将引导用户进行登录认证,这样我们也就不能真正的访问到App2了。针对这种应用场景,Cas也提供了对应的支持。

CAS代理模式原理

Cas Proxy可以让我们轻松的通过App1访问App2时通过Cas Server的认证,从而访问到App2。
   其主要原理是这样的,App1先通过Cas Server的认证,然后向Cas Server申请一个针对于App2的proxy ticket,之后在访问App2时把申请到的针对于App2的proxy ticket以参数ticket传递过去。App2的AuthenticationFilter将拦截到该请求,发现该请求携带了ticket参数后将放行交由后续的Ticket Validation Filter处理。Ticket Validation Filter将会传递该ticket到Cas Server进行认证,显然该ticket是由Cas Server针对于App2发行的,App2在申请校验时是可以校验通过的,这样我们就可以正常的访问到App2了。
  
同样,在App1代理访问App2认证成功后,在回话过期前再次访问App2,可以直接获取到数据,不用再次去cas server认证。

官网代理认证流程图:
在这里插入图片描述

五、 CAS代理配置

代理端和被代理端配置略有不同,如果一个服务同时扮演两种角色,可以一起配置

1)代理端配置

这里只需要在cas认证的基础上增加几个代理的配置,包括给票据认证器ticketValidator设置PGT存储容器,代理回调地址——绝对地址,认证过滤器CASAuthenticationFilter设置代理拦截地址—相对地址

/**
 * 票据验证,使用cas3.0 代理票据认证器
 * 传递cas server地址进行初始化
 */
@Bean
public Cas30ProxyTicketValidator ticketValidator(ProxyGrantingTicketStorage proxyGrantingTicketStorage) {
    Cas30ProxyTicketValidator validator = new Cas30ProxyTicketValidator(casServerPrefix);
    validator.setProxyGrantingTicketStorage(proxyGrantingTicketStorage);
    validator.setProxyCallbackUrl(casClientPrefix + "/proxyCallback");
    return validator;
}
@Bean
public ProxyGrantingTicketStorage proxyGrantingTicketStorage() {
    return new ProxyGrantingTicketStorageImpl();
} 

/**
 * cas filter类,针对/login/cas请求做用户认证
 * @param serviceProperties
 * @param provider
 * @return
 */
@Bean
public CasAuthenticationFilter casAuthenticationFilter(ServiceProperties serviceProperties,
                                ProxyGrantingTicketStorage proxyGrantingTicketStorage,
                                AuthenticationProvider provider) {
    CasAuthenticationFilter filter = new CasAuthenticationFilter();
    filter.setServiceProperties(serviceProperties);
    filter.setProxyReceptorUrl("/proxyCallback");
    filter.setProxyGrantingTicketStorage(proxyGrantingTicketStorage);
    filter.setAuthenticationManager(new ProviderManager(Arrays.asList(provider)));
    return filter;
}
2)被代理端配置
/**
 * 设置cas属性bean
 * serviceProperties.setAuthenticateAllArtifacts(true);
 * 设置带有ticket参数的请求都可以触发认证,主要在代理认证时使用
 * @return
 */
@Bean
public ServiceProperties serviceProperties() {
    ServiceProperties serviceProperties = new ServiceProperties();
    serviceProperties.setService(casClientPrefix + casClientLogin);
    serviceProperties.setAuthenticateAllArtifacts(true);
    return serviceProperties;
}

/**
 * 票据验证,使用cas3.0
 * 打开接收任何代理开关,这样可以接受任何代理,不太安全
 * 还可以设置代理链,指定允许代理的服务
 */
@Bean
public Cas30ProxyTicketValidator ticketValidator() {
    Cas30ProxyTicketValidator validator = new Cas30ProxyTicketValidator(casServerPrefix);
    validator.setAcceptAnyProxy(true);
    //设置代理链方式
//        validator.setAllowedProxyChains(new ProxyList());
    return validator;
}

/**
 1. cas filter类,针对/login/cas请求做用户认证
 2. filter.setAuthenticationDetailsSource(new ServiceAuthenticationDetailsSource(serviceProperties));
 3. 该设置可以在认证信息中记录请求原始url,不再使用spring security默认的 /login/cas
 */
@Bean
public CasAuthenticationFilter casAuthenticationFilter(ServiceProperties serviceProperties,
                                                       AuthenticationProvider provider) {
    CasAuthenticationFilter filter = new CasAuthenticationFilter();
    filter.setServiceProperties(serviceProperties);
    filter.setAuthenticationDetailsSource(new ServiceAuthenticationDetailsSource(serviceProperties));
    filter.setAuthenticationManager(new ProviderManager(Arrays.asList(provider)));
    return filter;
}

六、 CAS 系统中的票据:TGC、TGT 、ST 、PGT 、PGTIOU 、PT

票据名称解释
TGT(Ticket Grangting Ticket)TGT是CAS为用户签发的登录票据,拥有了TGT,用户就可以证明自己在CAS成功登录过。用户在CAS认证成功后,CAS生成Cookie(叫TGC),写入浏览器,同时生成一个TGT对象,放入自己的缓存,TGT对象的ID就是Cookie的值。当HTTP再次请求到来时,如果传过来的有CAS生成的Cookie,则CAS以此Cookie值为key查询缓存中有无TGT ,如果有的话,则说明用户之前登录过,如果没有,则用户需要重新登录。
TGC(ticket-granting cookie授权的票据证明,由 CAS Server 通过 SSL 方式发送给终端用户,存放用户身份认证凭证的Cookie。在浏览器和CAS Server间通讯时使用,并且只能基于安全通道传输(Https),是CAS Server用来明确用户身份的凭证。
ST(Service Ticket)ST是CAS为用户签发的访问某一service的票据。用户访问service时,service发现用户没有ST,则要求用户去CAS获取ST。用户向CAS发出获取ST的请求,如果用户的请求中包含Cookie,则CAS会以此Cookie值为key查询缓存中有无TGT,如果存在TGT,则用此TGT签发一个ST,返回给用户。用户凭借ST去访问service,service拿ST去CAS验证,验证通过后,允许用户访问资源。
PGT(Proxy Granting Ticket)Proxy Service的代理凭据。用户通过CAS成功登录某一Proxy Service后,CAS生成一个PGT对象,缓存在CAS本地,同时将PGT的值(一个UUID字符串)回传给Proxy Service,并保存在Proxy Service里。Proxy Service拿到PGT后,就可以为Target Service(back-end service)做代理,为其申请PT。
PGTIOU(Proxy Granting Ticket I Owe You)PGTIOU是CAS协议中定义的一种附加票据,它增强了传输、获取PGT的安全性。PGT的传输与获取的过程:Proxy Service调用CAS的serviceValidate接口验证ST成功后,CAS首先会访问pgtUrl指向的Https URL,将生成的 PGT及PGTIOU传输给proxy service,proxy service会以PGTIOU为key,PGT为value,将其存储在Map中;然后CAS会生成验证ST成功的XML消息,返回给Proxy Service,XML消息中含有PGTIOU,proxy service收到XML消息后,会从中解析出PGTIOU的值,然后以其为key,在Map中找出PGT的值,赋值给代表用户信息的Assertion对象的pgtId,同时在Map中将其删除。
PT(Proxy Ticket)PT是用户访问Target Service(back-end service)的票据。如果用户访问的是一个Web应用,则Web应用会要求浏览器提供ST,浏览器就会用Cookie去CAS获取一个ST,然后就可以访问这个Web应用了。如果用户访问的不是一个Web应用,而是一个C/S结构的应用,因为C/S结构的应用得不到Cookie,所以用户不能自己去CAS获取ST,而是通过访问proxy service的接口,凭借proxy service的PGT去获取一个PT,然后才能访问到此应用。

七、 未使用Spring Security的配置

若未使用Security,可以直接引入cas-client包,相关配置步骤基本一致
pom.xml中引入jar包

<dependency>
    <groupId>org.jasig.cas.client</groupId>
    <artifactId>cas-client-core</artifactId>
    <version>3.5.1</version>
</dependency>

相应application.properties配置

# 监听退出的接口,即所有接口都会进行监听
spring.cas.sign-out-filters=/*
# 需要拦截的认证的接口
spring.cas.auth-filters=/*
spring.cas.validate-filters=/*
spring.cas.request-wrapper-filters=/*
spring.cas.assertion-filters=/*
# 表示忽略拦截的接口,也就是不用进行拦截
spring.cas.ignore-filters=/test
spring.cas.cas-server-login-url=https://cas.hanshow.com:8443/cas/login
spring.cas.cas-server-url-prefix=https://cas.hanshow.com:8443/cas/
spring.cas.redirect-after-validation=true
spring.cas.use-session=true
spring.cas.server-name=http://localhost:9443
logging.level.web=debug
logging.level.sql=debug
logging.level.root=debug

以上配置信息注入到java bean——SpringCasAutoConfig中,在过滤器配置中使用

CAS过滤器配置

@Configuration
@Component
public class CasCustomConfig {

    @Resource
    SpringCasAutoconfig autoconfig;

    private static boolean casEnabled = true;

    public CasCustomConfig() {
    }

    @Bean
    public SpringCasAutoconfig getSpringCasAutoconfig() {
        return new SpringCasAutoconfig();
    }

    @Bean
    public ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> singleSignOutHttpSessionListener() {
        ServletListenerRegistrationBean<SingleSignOutHttpSessionListener> listener = new ServletListenerRegistrationBean<SingleSignOutHttpSessionListener>();
        listener.setEnabled(casEnabled);
        listener.setListener(new SingleSignOutHttpSessionListener());
        listener.setOrder(1);
        return listener;
    }

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

    /**
     * 该过滤器负责用户的认证工作
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean authenticationFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new AuthenticationFilter());
        filterRegistration.setEnabled(casEnabled);
        if (autoconfig.getAuthFilters().size() > 0) {
            filterRegistration.setUrlPatterns(autoconfig.getAuthFilters());
        } else {
            filterRegistration.addUrlPatterns("/*");
        }
        if (autoconfig.getIgnoreFilters() != null) {
            filterRegistration.addInitParameter("ignorePattern", autoconfig.getIgnoreFilters());
        }
        filterRegistration.addInitParameter("casServerLoginUrl", autoconfig.getCasServerLoginUrl());
        filterRegistration.addInitParameter("serverName", autoconfig.getServerName());
        filterRegistration.addInitParameter("useSession", autoconfig.isUseSession() ? "true" : "false");
        filterRegistration.addInitParameter("redirectAfterValidation", autoconfig.isRedirectAfterValidation() ? "true" : "false");
        filterRegistration.setOrder(4);
        return filterRegistration;
    }

    /**
     * 该过滤器负责对Ticket的校验工作,使用CAS 3.0协议
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean cas30ProxyReceivingTicketValidationFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new Cas30ProxyReceivingTicketValidationFilter());
        filterRegistration.setEnabled(casEnabled);
        if (autoconfig.getValidateFilters().size() > 0) {
            filterRegistration.setUrlPatterns(autoconfig.getValidateFilters());
        } else {
            filterRegistration.addUrlPatterns("/*");
        }
        filterRegistration.addInitParameter("casServerUrlPrefix", autoconfig.getCasServerUrlPrefix());
        filterRegistration.addInitParameter("serverName", autoconfig.getServerName());
        filterRegistration.setOrder(5);
        return filterRegistration;
    }

    @Bean
    public FilterRegistrationBean httpServletRequestWrapperFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new HttpServletRequestWrapperFilter());
        filterRegistration.setEnabled(true);
        if (autoconfig.getRequestWrapperFilters().size() > 0) {
            filterRegistration.setUrlPatterns(autoconfig.getRequestWrapperFilters());
        } else {
            filterRegistration.addUrlPatterns("/*");
        }
        filterRegistration.setOrder(6);
        return filterRegistration;
    }

    /**
     * 该过滤器使得可以通过org.jasig.cas.client.util.AssertionHolder来获取用户的登录名。
     * 比如AssertionHolder.getAssertion().getPrincipal().getName()。
     * 这个类把Assertion信息放在ThreadLocal变量中,这样应用程序不在web层也能够获取到当前登录信息
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean assertionThreadLocalFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
        filterRegistration.setFilter(new AssertionThreadLocalFilter());
        filterRegistration.setEnabled(true);
        if (autoconfig.getAssertionFilters().size() > 0) {
            filterRegistration.setUrlPatterns(autoconfig.getAssertionFilters());
        } else {
            filterRegistration.addUrlPatterns("/*");
        }
        filterRegistration.setOrder(7);
        return filterRegistration;
    }
}

根据以上配置,运行项目后,可以获取到登录的用户信息

@RestController
public class TestController {
    @RequestMapping("/getName")
    public Object getName(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        Assertion assertion = (Assertion) session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
        return assertion.getPrincipal().getName();
    }

八、 可能遇到的问题

1) Host配置

要成功访问CAS server,需要在本地host配置CAS server的域名映射

192.168.3.124 cas.hanshow.com

2) 证书问题

开发中,在首次访问CAS server时,会报:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building
failed:……

Java在请求某些不受信任的https网站时是会发生这种情况
两种解决方案:

  • 手动导入证书到本地证书库
  • 信任所有SSL证书

目前项目采用的第一种,详细步骤可参照博文:

https://blog.youkuaiyun.com/gabriel576282253/article/details/81531746

3) 跨域问题

在登录和登出时,都会发生302重定向,若前端调用后端接口发起重定向,会有跨域问题(毕竟要跳转到其他域名)
目前采用的解决方案:

  • 部署时将前端文件放于后端项目根目录,在访问时Spring Security会拦截请求自动跳转到CAS server,可解决登录跨域
  • 登出时是通过接口调用,后端只做session销毁,然后返回,前端完成登出跳转

以上是在使用Spring Security情况下,接入cas客户端所需配置。
用户登录后,还需要自定义资源权限相关的实现。

本文参考

  • https://blog.youkuaiyun.com/elim168/article/details/43560737
  • https://blog.youkuaiyun.com/Anumbrella/article/details/80821486

他们的是cas系列博客,对于cas的理解和使用有很大帮助,在此表示感谢

CAS单点登录重定向service参数硬编码 先说下问题,cas单点登录地址会带入service参数,这个参数可能会被有心人利用修改浏览器地址栏带入自己的重定向地址,例如: http://localhost:6212/cas/login?service=http://www.a.com 那么可能正常获取票据后就带到a了,当然有心人会伪造“类同源域名” 这个时候需要将自己需要的重定向地址硬编码到程序中。 源码发现这个参数service并不是单纯的String 而是一个 public interface Service extends Princip. 阅读详情

相关推荐

CAS认证系统基础

CAS认证系统基础 本文中重点介绍CAS是什么,能干什么? Filter又是什么,跟CAS有什么关系? 一、基本定义:     在了解原理之前,我们 先了解一下概念:    1、CAS=Central Authentication Service,中央认证服务,就是一个认证系统。     2、SSO:全程Single Sign On,单点登录,SSO是在多个

何新生(Daniel) 勇敢坚毅真正之才智乃刚毅之志向。 —— 拿破仑 3911

CAS单点登录开源框架解读(十一)--CAS单点登录代理模式之概述

解析代理模式 在接下来的文章中,我们将对CAS单点登录的代理模式进行解析。讲解如何对代理模式进行使用和测试 1. 代理模式时序图 下图为CAS单点登录代理模式下的序列图,网摘自https://apereo.github.io/cas/4.2.x/protocol/CAS-Protocol.html。 使用场景简单说明:当浏览器用户访问代理应用A,代理应用A中调用了被代理应用B的授权性资源,代理应...

joeljx的专栏 1613

jasig cas笔记(一):基础(非代理)认证流程

单点登录的概念不再赘述。而关于jasig cas 的认证流程,其实十分简单明了,直接上图: 上图中几个角色分别为:user(用户)、browser(浏览器)、cas server(jasig cas认证服务)、(app1)应用1、(app2)应用2。一、两个关键元素:ST、TGC ST:即service ticket;用于验证用户认证状态的一种凭证。当用户请求某个应用的资源时,若该用户尚未认证,

hxm_Code的专栏 1182

CAS5 代理模式

一、什么是CAS的代理认证   在我们的项目中,有这样一个场景:有两个服务holiday(节假日服务)和mainWeb(集成服务),这两个服务都集成了CAS,所有的请求都要经过CAS Server的认证。由于mainWeb内部会去调用holiday的服务,但是mainWeb的请求会被holiday配置的CAS拦截器AuthenticationFilter拦截并重定向到CAS Server。这样...

背着小书包一路追寻梦想 1959

CAS环境下的代理模式Java代码实现

代理模式是软件设计中一种常见且重要的设计模式,它为其他对象提供一种代理以控制对这个对象的访问。代理模式主要解决的是当直接访问某些对象时存在困难或需要增加额外处理时,如何让外部通过代理间接进行访问的问题。它广泛应用于业务逻辑层和数据访问层之间的解耦,以及安全、控制访问权限等场景。代理模式定义了一个中介角色,即“代理对象”,它持有对实际对象的引用,在客户端和目标对象之间起到中介的作用。它主要有以下几个特点:控制访问权限:代理可以控制对实际对象的访问权限,增强系统安全性。延迟初始化。

weixin_35750483的博客 555

CAS认证服务客户端库核心组件介绍

本文还有配套的精品资源,点击获取 简介:casclient.jar是CAS(中央认证服务)客户端库的一部分,属于"cas-client-java-2.1.1.zip"压缩包中的"dist"目录下的编译后的组件。该组件主要负责处理用户身份验证过程,实现单点登录(SSO),并支持与多种CAS协议(1.0、2.0、3.0和SAML 1.1)通信。它管理CAS票证、自动重写URL以...

weixin_42560991的博客 1520

CAS—认证原理

CAS,Central Authentication Service—中央认证服务,是Yale 大学发起的一个企业级的、开源的项目,旨在为Web应用系统提供一种可靠的SSO解决方案。下面简单介绍SSO,重点介绍CAS认证过程。 一、    SSO简介   1.1   概念   SSO英文全称Single Sign On,是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应

大鹏 4万+

CAS代理模式

Yale CAS proxy authentication. 博文链接:https://iroyce.iteye.com/blog/101899

Cas(09)——Cas Proxy原理,通过Cas Proxy访问其它Cas应用

通过Proxy访问其它Cas应用        考虑这样一种场景:有两个应用App1和App2,它们都是受Cas Server保护的,即请求它们时都需要通过Cas Server的认证。现需要在App1中通过Http请求访问App2,显然该请求将会被App2配置的Cas的AuthenticationFilter拦截并转向Cas Server,Cas Server将引导用户进行登录认证,这样我们也就

Elim的博客 1万+

水星路由器+群晖NAS+外网访问

水星路由器+群晖NAS+外网访问 有了公网IP,家里是水星路由器的 怎么设置外网访问 1.先电脑登录群晖的http://【你的群晖名】.quickconnect.to/ 2.【控制面板】进入设置 3.选择synology依次设置 ,【主机名称】就是你的名称。注意:左下角第7步,一定勾选。 4.下面进入192.168.1.1水星路由器设置。【IP与MAC绑定】点击NAS对应的【绑定】注意,点这里之前Nas一定设置了固定内网ip(后面补充 )。 5.【高级用户】-虚【拟服务器】。常用服务器不用选,其他的对应

wjxue201的博客 2600

RT-Thread Studio使用笔记(四):带片外Flash(W25Q128)的OTA(YModem)

前言 在学习OTA之前,请先参考上两篇博客写的关于SPI设备及W25Q128的使用方法,传送门: https://blog.youkuaiyun.com/tigerots/article/details/107423633 https://blog.youkuaiyun.com/tigerots/article/details/107933991 如何使用OTA 一. 制作BootLoader 打开Bootloader 在线获取地址,注册,并根据RT-thread官方文档生成BootLoader,官方文档已经写的很清楚,再此

tigerots的专栏 4008

CAS 4.2.x 版本代理认证实现

CAS 4.2.x 版本代理模式实现 一、CAS代理认证 请参阅本指南了解更多详情。 默认情况下启用对 CAS v1+ 协议的代理身份验证支持,因此利用代理身份验证功能完全是 CAS 客户端配置的问题。 二、什么是CAS的代理认证 举例这样一个场景:有两个服务,分别是【运维服务】和【资源管理服务】,这两个服务都集成了CAS,所有的请求都要经过CAS Server【认证中心】的认证。由于【运维服务】内部会去调用【资源管理服务】,但是【运维服务】的请求会被【资源管理服务】配置的CAS拦截器【Authentica

pitt1997的博客 1906

《uni-app 长列表优化:虚拟列表(vue-virtual-scroller)解决 1000+ 数据渲染卡顿》(附虚拟列表封装与多端适配)

本文详细介绍了虚拟列表技术在前端长列表渲染中的优化方案。针对传统v-for渲染导致的性能问题(内存占用高、渲染阻塞、滚动卡顿),提出基于vue-virtual-scroller的虚拟列表解决方案,通过可视区域渲染和DOM复用实现性能突破。文章包含核心原理、组件封装、多端适配及性能对比,并给出常见问题的解决方法。实践表明,该方案可将1000条数据的首次渲染时间从3800ms降至420ms,滚动FPS提升至55帧,显著改善用户体验。

qq_59041750的博客 2107

Spring Security CAS认证

13.7 CAS认证 13.7.1概述 JA-SIG生产一种称为CAS的企业级单点登录系统。与其他计划不同,JA-SIG的中央身份验证服务是开源的,广泛使用的,易于理解,独立于平台,并支持代理功能。Spring Security完全支持CAS,并提供从Spring Security的单应用程序部署到企业级CAS服务器保护的多应用程序部署的轻松迁移路径。 您可以在https://www.ape...

大强博客 1万+

作物生长模型Oryza V3实战9:控制文件参数详解

control.dat是ORYZA水稻模型的核心配置文件,主要包含三部分:1)基础参数设置与模拟时间定义;2)关键文件路径配置,包括土壤参数文件(soil.sol)、作物参数文件(cultivar.crp)、田间管理文件(manage.exp)及气象数据目录,同时指定输出结果文件(res.dat)和运行日志(model.log);3)可选参数和输出控制选项。该文件通过关联各类输入数据(气象、土壤、品种特性等)和输出结果,实现模型运行的全流程控制,支持参数调整后继续模拟和中断恢复功能。

221

基于Jeecgboot3.8.1的vue3版本前后端分离的flowable流程管理平台

基于Jeecgboot3.8.1的vue3版本前后端分离的flowable流程管理平台

宁波阿成的博客 1544

通过Proxy访问其它Cas应用

目录 1.1     原理 1.2     配置 1.2.1    代理端 1.2.2    被代理端 1.3     请求示例          考虑这样一种场景:有两个应用App1和App2,它们都是受Cas Server保护的,即请求它们时都需要通过Cas Server的认证。现需要在App1中通过Http请求访问App2,显然该请求将会被App2配置的Cas的Authenti

caomiao2006的专栏 1551

基于传统算法的半导体晶圆缺陷检测原理及代码(二)

了解基于传统算法的半导体晶圆缺陷检测原理和方法,对于深入理解半导体制造工艺和质量控制具有重要意义。在半导体制造技术持续创新的浪潮中,基于传统算法的缺陷检测技术也将不断演进,为半导体产业的高质量发展提供坚实可靠的技术支撑,确保在芯片制造的每一个环节都能精准识别和管控缺陷,推动半导体产业迈向更高的发展水平。基于传统算法的半导体晶圆缺陷检测技术在半导体制造的长期发展历程中扮演了重要角色,凭借其成熟的技术体系、较快的检测速度和相对较低的成本,在各个工艺阶段为保障晶圆质量发挥了关键作用。

m0_44975814的博客 2220

SpringBoot 集成cas认证

之前一篇介绍了cas认证服务的整个流程;这篇文章Springboot框架里面如何整合cas实现整个认证的流程; 1>首先引入Springsecurity cas的依赖jar compile "org.springframework.security:spring-security-cas" 2>配置CasSecurityConfig类 @Configuration publ...

xiaoguangtouqiang的博客 1万+

大规模新闻聚合爬虫实战:Python爬取数百万新闻数据的完整指南

本文详细介绍了如何构建一个大规模新闻聚合爬虫,结合Python异步爬虫技术,实现高效、稳定的新闻数据采集。增加NLP模块对新闻内容做自动分类、情感分析。引入机器学习模型检测新闻真实性。使用分布式爬虫框架进一步提升规模。增加多媒体内容抓取与处理。

2201_76125261的博客 1554

【WRF教程第3.5期】预处理系统 WPS 详解:以4.5版本为例

预处理系统 WPS 详解:以4.5版本为例

WW、forever的博客 1422

CAS3.4 代理模式详细配置

版本 CAS服务器版本:3.4.2 CAS客户端for JAVA版本:3.1.10   前言 CAS3.4版本的资料在网上实在是少的可怜啊,幸亏官方网站所提供的资料帮助我完成了代理模式的配置,不过读E文真的很费劲。   在详细配置之前先说下对代理模式的认证,在网上查资料时看到有人说代理模式是服务于C/S架构的程序,还举例说什么看电影什么的,

qingrx的专栏 7290

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

深入理解CAS-认证原理

CAS,Central Authentication Service—中央认证服务,旨在为Web应用系统提供一种可靠的SSO解决方案。下面简单介绍SSO,重点介绍CAS认证过程。 一、SSO简介   1.1 概念   SSO英文全称Single Sign On,是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。   1.2 角色   一般 SSO 体系主要角色有三种:   * User (多个)   ...

向着高亮的地方 5719

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Cas(09)——通过Proxy访问其它Cas应用

通过Proxy访问其它Cas应用   目录 1.1     原理 1.2     配置 1.2.1    代理端 1.2.2    被代理端 1.3     请求示例          考虑这样一种场景:有两个应用App1和App2,它们都是受Cas Server保护的,即请求它们时都需要通过Cas Server的认证。现需要在App1中通过Http请求访问App2,显然该请求将

zylzb的专栏 1336

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

基于认证中心的单点登录系统CAS

本文描述了基于认证中心的单点登录系统,采用独立的认证中心是实现企业单点登录非常好的应用实践。 CAS需要较高的集成度,在需要实现单点登录的系统,配置认证中心地址,和认证中心交互获得用户信息。 文尾比较了,通过子域名方式和Oauth方式实现单点登录系统的差别。 基于认证中心的单点登录原理是基于ticket实现。CAS系统就是一个集成化程度很好的基于ticket单点登录系统。 单点登录步骤...

u011893782的博客 1871

cas之认证原理

CAS,Central Authentication Service—中央认证服务,是Yale 大学发起的一个企业级的、开源的项目,旨在为Web应用系统提供一种可靠的SSO解决方案。下面简单介绍SSO,重点介绍CAS认证过程。 一、    SSO简介   1.1   概念   SSO英文全称Single Sign On,是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应

小人物 866
上一篇: idea配置部署cas-server5.3并debug其源码
下一篇: cas票据过期策略
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值