ITPub博客

首页 > IT职业 > IT职场 > ticket 在过期前[下 过期时间 参数] 可以使用的次数

ticket 在过期前[下 过期时间 参数] 可以使用的次数

投稿 IT职场 作者:ecclw459 时间:2026-01-07 18:05:20 0 删除 编辑

ticket 过期策略配置

<!-- TGT 配置-->
	<bean id="serviceTicketExpirationPolicy" class="org.jasig.cas.ticket.support.MultiTimeUseOrTimeoutExpirationPolicy">
    
		<!-- This argument is the number of times that a ticket can be used before its considered expired. 
        (ticket 在过期前[下 过期时间 参数] 可以使用的次数)
        -->
		<constructor-arg
			index="0"
			value="999999999" />
		
		<!-- This argument is the time a ticket can exist before its considered expired.  
        ( 过期时间 单位:毫秒)
        -->
		<constructor-arg
			index="1"
			value="100000" />
	</bean>
	<!--ST 配置 -->
	<bean id="grantingTicketExpirationPolicy" class="org.jasig.cas.ticket.support.TimeoutExpirationPolicy">
		<!-- This argument is the time a ticket can exist before its considered expired. 
        (ticket 在不活跃的时候过期时间 毫秒)
         -->
		<constructor-arg
			index="0"
			value="7200000" />
	</bean>

参考

TGC: Ticket Granting Cookie

CAS 会将生成的 TGT 放在 session 中, 而 TGC 就是这个 session 的唯一标识(sessionId), 可以认为是 TGT 的key, 为 TGT 就是 TGC 的 value, TGC 以 cookie 的形式保存在浏览器中, 每个请求都会尝试携带 TGC; (每个服务都会在 session 和 cookie 中保存对应的 TGT 和 TGC)

TGT: Ticket Granting Ticket

TGT 是CAS 为用户签发的登录 ticket, 也是用于验证用户登录成功的唯一方式; TGT 封装了 Cookie 值以及 Cookie 值对应的用户信息, CAS 通过 Cookie 值(TGC)为 key 查询缓存中有无 TGT(TGC:TGT(key:value)), 如果有的话就说明用户已经登录成;

ST: Service Ticket

ST 是当用户访问某一服务时提供的 ticket; 用户在访问其他服务时, 发现没有 cookie 或 ST , 那么就会302到 CAS 服务器获取 ST; 然后会携带着 ST 302 回来;

客户端 (XML形式配置)

  1. 首先需要做的是将应用的登录认证入口改为使用 CasAuthenticationEntryPoint;
  <!-- 指定登录入口为casEntryPoint -->
   <security:http  entry-point-ref="casEntryPoint">
      ...   </security:http>
  1. 所以首先我们需要配置一个 CasAuthenticationEntryPoint对应的bean, 然后指定需要进行登录认证时使用该 AuthenticationEntryPoint;
<!-- 认证的入口 -->
   <bean id="casEntryPoint"
      class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
      <!-- Cas Server的登录地址, elim是我的计算机名 -->
      <property name="loginUrl" value="https://elim:8443/cas/login" />
      <!-- service相关的属性 -->
      <property name="serviceProperties" ref="serviceProperties" />
   </bean>
  1. 配置CasAuthenticationEntryPoint时需要指定一个 ServiceProperties, 该对象主要用来描述service(Cas概念)相关的属性, 主要是指定在Cas Server认证成功后将要跳转的地址;
<!-- 指定service相关信息 -->
   <bean id="serviceProperties"class="org.springframework.security.cas.ServiceProperties">
      <!-- Cas Server认证成功后的跳转地址, 这里要跳转到我们的Spring Security应用, 之后会由CasAuthenticationFilter处理, 默认处理地址为/j_spring_cas_security_check -->
      //<!>本地地址了, 这里开始就是本地Spring Security 流程了, 再由 cas filter 封装 UsernamePasswordAuthenticationToken 
      //再到 AuthenticationManager, 到 AuthenticationProvider 流程..      <property name="service"
         value="http://elim:8080/app/j_spring_cas_security_check" />
   </bean>
  1. 之后我们需要配置一个 CasAuthenticationFilter, 并将其放置在Filter链表中CAS_FILTER的位置, 以处理Cas Server认证成功后的页面跳转, 用以在Spring Security中进行认证;

该Filter会将Cas Server传递过来的ticket(Cas概念)封装成一个 Authentication(对应UsernamePasswordAuthenticationToken, 其中ticket作为该Authentication的password), 然后传递给 AuthenticationManager进行认证;

  <security:http entry-point-ref="casEntryPoint">
      ...        <!-- 定义CasAuthenticationFilter 并将其放置在Filter链表中CAS_FILTER的位置-->
      <security:custom-filter ref="casFilter" position="CAS_FILTER"/>
      ...   </security:http>
   <bean id="casFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
      <property name="authenticationManager" ref="authenticationManager" />
      <!-- 指定处理地址, 不指定时默认将会是"/j_spring_cas_security_check" -->
      <property name="filterProcessesUrl" value="/j_spring_cas_security_check"/>
   </bean>
  1. CasAuthenticationFilter会将封装好的包含Cas Server传递过来的ticket的Authentication对象传递给 AuthenticationManager进行认证;
<security:authentication-manager alias="authenticationManager"><!-- 给AuthenticationManager 提供一个 认证 ; 参考: 细谈认证过程 5-->
      <security:authentication-provider ref="casAuthenticationProvider"/>
   </security:authentication-manager>
  1. 默认的AuthenticationManager实现类为ProviderManager, 而ProviderManager中 真正进行认证的是AuthenticationProvider;

所以接下来我们要在AuthenticationManager中配置一个能够处理 CasAuthenticationFilter传递过来的Authentication对象的AuthenticationProvider实现,  CasAuthenticationProvider;

<!> 真正认证逻辑bean 
 <bean id="casAuthenticationProvider"
   class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
      <!-- 通过username来加载UserDetails -->
      <property name="authenticationUserDetailsService">
         <beanclass="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">            <!-- 真正加载UserDetails的UserDetailsService实现 -->
            <constructor-arg ref="userDetailsService" />
         </bean>
      </property>
      <property name="serviceProperties" ref="serviceProperties" />
      <!-- 配置TicketValidator在登录认证成功后验证ticket -->
      <property name="ticketValidator">
         <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
            <!-- Cas Server访问地址的前缀, 即根路径-->
            <constructor-arg index="0" value="https:// elim:8443/cas" />
         </bean>
      </property>
      <property name="key" value="key4CasAuthenticationProvider" />
   </bean>

CasAuthenticationProvider首先会利用TicketValidator(Cas概念)对Authentication中包含的ticket信息进行认证;

认证通过后将利用持有的 AuthenticationUserDetailsService 根据认证通过后回传的Assertion对象中拥有的username加载用户对应的UserDetails,

即主要是加载用户的相关权限信息GrantedAuthority; 然后构造一个 CasAuthenticationToken进行返回; 之后的逻辑就是正常的Spring Security的逻辑了;

访问测试

http://127.0.0.1/cas-server/login
https://127.0.0.1:8443/cas-server/login

客户端 (Java Bean形式配置)

<!-- security 对CAS支持 --><dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-cas</artifactId></dependency>
    //入口点
   @Bean
	public CasAuthenticationEntryPoint casAuthenticationEntryPoint() {		CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint();
		casAuthenticationEntryPoint.setLoginUrl(casProperties.getServerPrefix()+casProperties.getServerLogin());
		casAuthenticationEntryPoint.setServiceProperties(serviceProperties());		return casAuthenticationEntryPoint;
	}    // 本地缓存认证
    @Bean
  	public CasLocalCacheAuthenticationFilter casLocalCacheAuthenticationFilter()  {
    	CasLocalCacheAuthenticationFilter ccaf;    	try {
    		ccaf = new CasLocalCacheAuthenticationFilter(casProperties, redisTemplate, casUserDetailsService());
		} catch (Exception e) {
			e.printStackTrace();			throw new RuntimeException(e.getMessage() );
		}  		return ccaf;
  	}    // cas 认证过滤器
    @Bean
	public CasAuthenticationFilter casAuthenticationFilter() throws Exception {		CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
		casAuthenticationFilter.setAuthenticationManager(authenticationManager());
		casAuthenticationFilter.setFilterProcessesUrl(casProperties.getAppLogin());
		casAuthenticationFilter.setAuthenticationSuccessHandler(casAuthenticationSuccessHandler());		return casAuthenticationFilter;
	}    ////////////认证相关处理
    @Bean
    @Override
	protected AuthenticationManager authenticationManager() {
		List<AuthenticationProvider> p = new ArrayList<AuthenticationProvider>(1);
		p.add(casAuthenticationProvider());		ProviderManager authenticationManager = new ProviderManager(p);		return authenticationManager;
	}    @Bean
	public CasAuthenticationProvider casAuthenticationProvider() {		CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();		try {
			casAuthenticationProvider.setAuthenticationUserDetailsService(casUserDetailsService());
		} catch (Exception e) {
			e.printStackTrace();			throw new RuntimeException(e.getMessage() );
		}
		casAuthenticationProvider.setServiceProperties(serviceProperties());
		casAuthenticationProvider.setTicketValidator(cas20ServiceTicketValidator());
		casAuthenticationProvider.setKey("jk_www_123ProviderKey");		return casAuthenticationProvider;
	}	@Bean
	public Cas20ServiceTicketValidator cas20ServiceTicketValidator() {		return new Cas20ServiceTicketValidator(casProperties.getServerPrefix());
	}	
	@Bean
	public ServiceProperties serviceProperties(soccer.soccer.zuq8.info) {		ServiceProperties serviceProperties = new ServiceProperties();
		serviceProperties.setService(casProperties.getAppPrefix()+ casProperties.getAppLogin());
		serviceProperties.setAuthenticateAllArtifacts(true);		return serviceProperties;
	}    @Bean
	public CasAuthenticationSuccessHandler casAuthenticationSuccessHandler()  {    	CasAuthenticationSuccessHandler casAuthenticationSuccessHandler = new CasAuthenticationSuccessHandler(this.casProperties, redisTemplate);		return casAuthenticationSuccessHandler;
	}    
    // 本地 UserDetailsService
	@Bean	
	@ConditionalOnMissingBean( value={AuthenticationUserDetailsService.class} )
 	public AuthenticationUserDetailsService casUserDetailsService() throws Exception { 		return new CasUserDetailsServiceImp();
 	}     //登出
    @Bean
	public CasLogoutFilter casLogoutFilter(gov.cb.zuzb.info) {		return new CasLogoutFilter(casProperties, redisTemplate);
	}    
    //配置
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
      	log.info("当前使用安全配置是: cas");
    	ExpressionInterceptUrlRegistry eiur=httpSecurity                // 禁用 CSRF
                .csrf().disable()                // 授权异常
                .exceptionHandling().authenticationEntryPoint(casAuthenticationEntryPoint() ).and()                // 不创建会话
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()    	//
		    	httpSecurity
					.formLogin()
					.loginProcessingUrl(casProperties.getAppLogin());                // 防止iframe 造成跨域
                .and().headers().frameOptions().disable();
        httpSecurity
        		.addFilterAt(casLogoutFilter(), LogoutFilter.class)
                .addFilterBefore(casAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(casLocalCacheAuthenticationFilter(), CasAuthenticationFilter.class);
      
    }

定义一个 CasProperties 配置类,用于将properties文件指定的内容注入以方便使用

public class CasProperties {	private String serverPrefix;	private String serverLogin;	private String serverLogout;	//
	private String appPrefix;	private String appLogin;	private String appLogout;

注意1 CasAuthenticationFilter

CasAuthenticationFilter 认证过滤器

@Beanpublic CasAuthenticationFilter casAuthenticationFilter() throws Exception {    CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();    //根据 spring securiry 步骤 authenticationManager 会调用 Provider list 认证 规则
    //所以还要把CasAuthenticationProvider  注给 authenticationManager, 最好覆盖父的方法, 自己写.. 先不管了
    List<AuthenticationProvider> p = new ArrayList<AuthenticationProvider>(1);
    p.add(casAuthenticationProvider(gov.zuqiu.yc.jrzb1.info));    ProviderManager authenticationManager = new ProviderManager(p);
    casAuthenticationFilter.setAuthenticationManager(authenticationManager);
    casAuthenticationFilter.setFilterProcessesUrl(casProperties.getAppLogin());//cas 的回调 登陆地址
    return casAuthenticationFilter;


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048957/viewspace-3107305/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2026-01-07

  • 博文量
    108
  • 访问量
    102109