CAS 4.X.X 客户端循环重定向如何查找原因以及解决方案?

发布于 2022-09-06 23:35:21 字数 8905 浏览 14 评论 0

问题描述

CAS Server(支持https)下存在client1,client2,client3多个应用,其中client1client2可以正常支持单点登录,但是client3却不行, 出现的问题是当在CAS Server登录后,网页会在https://cas-server/login?service=https://localhost:8443/cas-client3/loginhttps://localhost:8443/cas-client3/login?ticket=ST-1645-XXXXXXX-cas01.example.org之间循环重定向,导致网页不能正常访问

问题截图

clipboard.png

clipboard.png

spring security和CAS的配置如下

配置文件

# CAS 相关配置
app:
  login:
    url: /login
  logout:
    url: /logout
  server:
    host:
      url: https://localhost:8443/cas-client3

cas:
  server:
    host:
      url: https://cas-server
      login_url: ${cas.server.host.url}/login
      logout_url: ${cas.server.host.url}/logout?service=${app.server.host.url}

配置类

import com.cloume.mooc.security.MyPermissionEvaluator;
import com.cloume.mooc.security.SpringContextUtil;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.security.cas.web.CasAuthenticationFilter;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;

import javax.annotation.Resource;
import java.util.Map;

/**
 * spring security配置
 * <p>
 * Created by surpass.wei@gmail.com on 2017/7/26.
 */
@Configuration
@EnableWebSecurity //   启用web权限(spring boot无须该注解)
@EnableGlobalMethodSecurity(prePostEnabled = true) //启用方法验证
@Profile("cas")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    private CasProperties casProperties;

    /**
     * 用户认证配置
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
        auth.authenticationProvider(casAuthenticationProvider());
    }

    /**
     * 请求授权配置
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // 允许所有用户访问的路径
                .antMatchers("/html/**")
                .permitAll()
                .expressionHandler(httpSecurityExpressionHandler())
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .loginProcessingUrl("/login")
                .permitAll()
                .and()
                .rememberMe()
                .tokenValiditySeconds(31536000)
                .and()
                .csrf()
                .disable()
                .logout()
                .permitAll();

        http.exceptionHandling().authenticationEntryPoint(casAuthenticationEntryPoint())
                .and()
                .addFilter(casAuthenticationFilter())
                .addFilterBefore(casLogoutFilter(), LogoutFilter.class)
                .addFilterBefore(singleSignOutFilter(), CasAuthenticationFilter.class);

        http.csrf().disable(); //禁用CSRF
    }

    /**
     * 指定service相关信息
     */
    @Bean
    public ServiceProperties serviceProperties() {
        ServiceProperties serviceProperties = new ServiceProperties();
        serviceProperties.setService(casProperties.getAppServerUrl() + casProperties.getAppLoginUrl());
        serviceProperties.setAuthenticateAllArtifacts(true);
        return serviceProperties;
    }

    @Bean
    public SessionRegistry getSessionRegistry() {
        return new SessionRegistryImpl();
    }

    @Bean
    public DefaultWebSecurityExpressionHandler httpSecurityExpressionHandler() {

        DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(new MyPermissionEvaluator());

        return expressionHandler;
    }

    @Bean
    public DefaultWebSecurityExpressionHandler webSecurityExpressionHandler() {

        final Map<String, DefaultWebSecurityExpressionHandler> expressionHandlers =
                SpringContextUtil.getApplicationContext().getBeansOfType(DefaultWebSecurityExpressionHandler.class);
        if (expressionHandlers.values().toArray()[0] != null) {
            ((DefaultWebSecurityExpressionHandler) expressionHandlers.values().toArray()[0]).setPermissionEvaluator(new MyPermissionEvaluator());
        }

        return (DefaultWebSecurityExpressionHandler) expressionHandlers.values().toArray()[0];
    }

    /**
     * CAS认证过滤器
     */
    @Bean
    public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
        CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
        casAuthenticationFilter.setAuthenticationManager(authenticationManager());
        casAuthenticationFilter.setFilterProcessesUrl(casProperties.getAppLoginUrl());
        //  认证成功后的处理
        //casAuthenticationFilter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler("/html/user.html"));
        return casAuthenticationFilter;
    }

    /**
     * cas 认证 Provider
     */
    @Bean
    public CasAuthenticationProvider casAuthenticationProvider() {
        CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
        casAuthenticationProvider.setAuthenticationUserDetailsService(customUserDetailsService());
        //casAuthenticationProvider.setUserDetailsService(customUserDetailsService()); //这里只是接口类型,实现的接口不一样,都可以的。
        casAuthenticationProvider.setServiceProperties(serviceProperties());
        casAuthenticationProvider.setTicketValidator(cas20ServiceTicketValidator());
        casAuthenticationProvider.setKey("casAuthenticationProviderKey");
        return casAuthenticationProvider;
    }

    /**
     * 用户自定义的AuthenticationUserDetailsService
     */
    @Bean
    public AuthenticationUserDetailsService<CasAssertionAuthenticationToken> customUserDetailsService() {
        return new CustomUserDetailsService();
    }

    @Bean
    public Cas20ServiceTicketValidator cas20ServiceTicketValidator() {
        return new Cas20ServiceTicketValidator(casProperties.getCasServerUrl());
    }

    /**
     * CAS认证的入口
     */
    @Bean
    public CasAuthenticationEntryPoint casAuthenticationEntryPoint() {
        CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint();
        casAuthenticationEntryPoint.setLoginUrl(casProperties.getCasServerLoginUrl());
        casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
        return casAuthenticationEntryPoint;
    }

    /**
     * CAS请求单点退出过滤器
     */
    @Bean
    public LogoutFilter casLogoutFilter() {
        LogoutFilter logoutFilter = new LogoutFilter(casProperties.getCasServerLogoutUrl(), new SecurityContextLogoutHandler());
        logoutFilter.setFilterProcessesUrl(casProperties.getAppLogoutUrl());    //  设置处理登出的路径
        return logoutFilter;
    }

    /**
     * CAS单点登出过滤器
     */
    @Bean
    public SingleSignOutFilter singleSignOutFilter() {
        SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
        singleSignOutFilter.setCasServerUrlPrefix(casProperties.getCasServerUrl());
        singleSignOutFilter.setIgnoreInitConfiguration(true);
        return singleSignOutFilter;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

痞味浪人 2022-09-13 23:35:21

每次提交完问题, 总是就可以自己找到解决方案, 是运气好吗? 折磨了我三天的问题终于解决了, 而导致这个问题的原因居然是spring boot(1.3.x)与cas(4.2.x)版本不兼容导致, 解决方案很简单, 升级spring boot版本到1.5.x, cas不用指定版本号(会根据spring-boot-starter-parent自动适应)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文