4) Spring Boot + Spring Security集成CAS

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010475041/article/details/79592661

4) Spring Boot + Spring Security集成CAS

预期效果:
1. 访问客户端时跳转到cas登录
2. 登录完后,展示默认的用户信息
3. 对cas用户进行用户映射

分支代码:https://github.com/grissomsh/cas/tree/1.x-integration-spring-boot


cas校验流程:

  1. 用户访问业务系统(client)
  2. 无权限时跳转到cas(服务端),并且携带参数为service=${客户端url},所以我们看到登录页时浏览器路径为 http://localhost:8080/login?service=http%3A%2F%2Flocalhost%3A8123%2Flogin
  3. 当用户在cas处登录完后,会颁发一个ticket带回client端,如http://localhost:8123/login/cas?ticket=xxxxx
  4. 业务系统获取到ticket后,拿这个ticket请求cas获取对应的登录用户
  5. cas返回对应的用户信息,业务系统再对该用户进行身份映射再次认证,则完成本次登录

a. 项目搭建

pom.xml

<!--核心依赖-->
<dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-cas</artifactId>
</dependency>

b. 项目配置

CasSecurityConfig.java

注意casAuthenticationProvider()方法创建的bean,该bean可以设置用户映射,正常来说,例如通过第三方github登录,这里返回的openid,是github的用户id,则需要对用户进行映射或做用户绑定,则在这里做手脚

//http://www.baeldung.com/spring-security-cas-sso
@Configuration
public class CasSecurityConfig {
    //cas服务
    @Value("${cas.server.url:http://localhost:8080}")
    private String casServerUrl;

    @Bean
    public ServiceProperties serviceProperties() {
        ServiceProperties serviceProperties = new ServiceProperties();
        //本机服务,访问/login/cas时进行校验登录
        serviceProperties.setService("http://localhost:8123/login/cas");
        serviceProperties.setSendRenew(false);
        return serviceProperties;
    }

    @Bean
    @Primary
    public AuthenticationEntryPoint authenticationEntryPoint(
            ServiceProperties sP) {

        CasAuthenticationEntryPoint entryPoint
                = new CasAuthenticationEntryPoint();
        //cas登录服务
        entryPoint.setLoginUrl(casServerUrl + "/login");
        entryPoint.setServiceProperties(sP);
        return entryPoint;
    }

    @Bean
    public TicketValidator ticketValidator() {
        //指定cas校验器
        return new Cas30ServiceTicketValidator(
                casServerUrl);
    }

    //cas认证
    @Bean
    public CasAuthenticationProvider casAuthenticationProvider() {

        CasAuthenticationProvider provider = new CasAuthenticationProvider();
        provider.setServiceProperties(serviceProperties());
        provider.setTicketValidator(ticketValidator());
        //固定响应用户,在生产环境中需要额外设置用户映射
        provider.setUserDetailsService(
                s -> new User("auth-user", "123", true, true, true, true,
                        AuthorityUtils.createAuthorityList("ROLE_ADMIN")));
        provider.setKey("CAS_PROVIDER_LOCALHOST_8123");
        return provider;
    }


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

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

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

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

WebSecurityConfig.java

注意,
1.casAuthenticationFilter()创建的bean为核心,所以必须设置anthenticationManager,cas返回的ticket由他来校验
2. 由于设置的ServicePropertiesbean响应路径为/cas/login,所以权限配置处必须允许访问到,否则会出现死循环
3. 入口点为casAuthenticationEntryPoint

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    private AuthenticationProvider authenticationProvider;

    @Autowired
    private SingleSignOutFilter singleSignOutFilter;

    @Autowired
    private LogoutFilter logoutFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //所有都需要认证才能访问
        //由于设置了验证filter访问为,/login/cas,所以必须通过验证,否则出现死循环
        http
                .authorizeRequests().antMatchers("/login/cas").permitAll()
                .and()
                .authorizeRequests().anyRequest().authenticated()
                .and()
                .httpBasic().authenticationEntryPoint(authenticationEntryPoint)
                .and()
                .logout().logoutSuccessUrl("/logout")
                .and()
                .addFilterBefore(singleSignOutFilter, CasAuthenticationFilter.class).addFilterBefore(logoutFilter, LogoutFilter.class);
    }

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

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



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


    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }
}

b. 测试

  • 启动sso-server
  • 启动sso-integration-spring-boot

访问:http://localhost:8123/profile

采用默认帐号casuser/Mellon登录完成后,响应映射用户auth-user的相关数据

下载sso-server代码

猜你喜欢

转载自blog.csdn.net/u010475041/article/details/79592661