SpringBoot 集成cas认证

之前一篇介绍了cas认证服务的整个流程;这篇文章Springboot框架里面如何整合cas实现整个认证的流程;

1>首先引入Springsecurity cas的依赖jar

compile "org.springframework.security:spring-security-cas"

2>配置CasSecurityConfig类

@Configuration
public class CasSecurityConfig {

    @Value("${cas.server.url}")
    private String casServerUrl;

    @Value("${cas.service.home}")
    private String serverHome;

    @Value("${cas.service.backEndService}")
    private String backEndService;

    @Value("${cas.server.prefix}")
    private String casServerUrlPrefix;

    @Autowired
    private CustomCasUserDetailsService customCasUserDetailsService;

    @Bean
    public ServiceProperties serviceProperties() {
        ServiceProperties serviceProperties = new ServiceProperties();
        serviceProperties.setService(backEndService + "/login/cas");
        serviceProperties.setSendRenew(false);
        return serviceProperties;
    }

    @Bean
    @Primary
    public AuthenticationEntryPoint authenticationEntryPoint(
        ServiceProperties sP) {
        CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint();
        //cas登录服务
        entryPoint.setLoginUrl(casServerUrl + "/cas/login");
        entryPoint.setServiceProperties(sP);

        return entryPoint;
    }

    @Bean
    public TicketValidator ticketValidator() {
        return cas30ProxyTicketValidator();
    }

    TicketValidator cas30ProxyTicketValidator() {
        // 是否开启代理
        Cas30ProxyTicketValidator cas30ProxyTicketValidator = new Cas30ProxyTicketValidator(casServerUrlPrefix);
        cas30ProxyTicketValidator.setProxyGrantingTicketStorage(new ProxyGrantingTicketStorageImpl());
        cas30ProxyTicketValidator.setAcceptAnyProxy(true);
        cas30ProxyTicketValidator.setURLConnectionFactory(new SophonHttpsURLConnectionFactory());
        return cas30ProxyTicketValidator;
    }


    @Bean
    public CasAuthenticationProvider casAuthenticationProvider() {
        CasAuthenticationProvider provider = new CasAuthenticationProvider();
        provider.setServiceProperties(serviceProperties());
        provider.setTicketValidator(ticketValidator());
        provider.setAuthenticationUserDetailsService(customCasUserDetailsService);
        provider.setKey("an_id_for_this_auth_provider_only");
        return provider;
    }

    @Bean
    public SecurityContextLogoutHandler securityContextLogoutHandler() {
        return new SecurityContextLogoutHandler();
    }

    @Bean
    public LogoutFilter logoutFilter() {
        //退出后转发路径
        LogoutFilter logoutFilter = new LogoutFilter(
            casServerUrl + "/cas/logout?service=" + serverHome,
            securityContextLogoutHandler());
        logoutFilter.setLogoutRequestMatcher(new AntPathRequestMatcher("/api/logout"));
        return logoutFilter;
    }

    @Bean
    public SingleSignOutFilter singleSignOutFilter() {
        //单点退出
        SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
        singleSignOutFilter.setCasServerUrlPrefix(casServerUrlPrefix);
        singleSignOutFilter.setIgnoreInitConfiguration(true);
        return singleSignOutFilter;
    }

    //设置退出监听
    @EventListener
    public SingleSignOutHttpSessionListener singleSignOutHttpSessionListener(
        HttpSessionEvent event) {
        return new SingleSignOutHttpSessionListener();
    }
}

1)ServiceProperties配置了认证成功之后跳转的地址,cas在认证成功之后返回这个地址,并携带ticket;所以注意这个地址在springSecurity中一定是permitAll;不然会出现死循环;这里默认就使用这个地址"/login/cas",不然会有问题,后面会详细说;

2)AuthenticationEntryPoint配置了cas认证服务器的地址;

3)TicketValidator配置了校验ticket的类,应用接收到ticket之后,会通过这个类向cas认证服务器发送校验的请求校验ticket的有效性;

4)CasAuthenticationProvider 包含了校验ticket的配置以及校验成功之后获取用户信息的配置;这里配置的是CustomCasUserDetailsService

5)casServerUrlPrefix是cas的前缀地址,比如https://gg-sophon-13:8393/cas

3>添加配置

在SecurityConfiguration中添加cas的过滤器,如图所示

同时添加如下配置bean

@Override
    protected AuthenticationManager authenticationManager(){
        //设置cas认证提供
        return new ProviderManager(
            Arrays.asList(authenticationProvider));
    }

    @Bean
    public CasAuthenticationFilter casAuthenticationFilter(ServiceProperties sp) {
        //cas认证过滤器,当触发本filter时,对ticket进行认证
        CasAuthenticationFilter filter = new CasAuthenticationFilter();
        filter.setServiceProperties(sp);
        filter.setAuthenticationManager(authenticationManager());
        filter.setAuthenticationSuccessHandler(new CasAuthenticationSuccessHandler());
        return filter;
    }

整个配置到这里基本就结束了,下面跟踪下源码,解释下自己的两个疑问:

1.为什么serviceProperties.setService的地址后缀要是"/login/cas"?我改成其他的行不行,比如"/login/cas123"

2.具体校验ticket的逻辑是怎么处理的;

4>疑问解释

1)我把地址改成了"/login/cas123"

结果如图所示

那么为什么地址是"/login/cas"的时候就可以成功解析到ticket,然后去处理,改成"/login/cas123"就不行了那?带着疑问我断点调试了源代码发现

这里的返回值是ture,所以不需要认证,然后又没有一个接口或者页面对应就404了;跟踪进去这里的requiresAuthentication所做的操作

这里的match匹配的url是"/login/cas",而我们的request的地址是"/login/cas123",当然不匹配了;那么这个match中的地址是在哪里设置的那,我们看下AbstractAuthenticationProcessingFilter的子类CasAuthenticationFilter

在构造的时候默认这个地址就是"/login/cas";第一个问题解决了

2)第二个疑问,ticket拿到之后怎么处理的,这个是封装的,但是还是想看一下具体的逻辑;

跟踪到父类具体逻辑应该在这里

AbstractUrlBasedTicketValidator这个类里面

构造个ticket的url,根据cas的协议去校验,这个url地址是

https://gg-sophon-13:8393/cas/p3/proxyValidate?ticket=ST-218-ckNP-WOYieH2dg4dLZp2FUiw-xE-gg-sophon-13&service=http%3A%2F%2Flocalhost%3A8080%2Flogin%2Fcas

p3/proxyValidate 是api地址,应该是根据不同的cas协议,这个地址也是固定的,后面追加上ticket以及service地址;

验证完ticket之后,cas认证服务器返回用户的信息,以map的方式进行村粗;如图所示

然后调用我们之前定义的CustomCasUserDetailsService类loadUserDetails方法解析用户信息,之后存储在session中;

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值