springBoot-springSecurity-cas5.3(记录一下)

一:在pom文件中引入security对cas支持的依赖

        <!--    security对cas支持    -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-cas</artifactId>
        </dependency>

二:在application.properties文件中引入cas服务端相关路径

cas:
  server_host_url: http://www.casserver.com:8443
  server_host_login_url: http://www.casserver.com:8443/login
  server_host_logout_url: http://www.casserver.com:8443/logout?        
  service=http://localhost:8084/say
  app_server_host_url: http://localhost:8084
  app_login_url: /login
  app_logout_url: /logout

三:定义CustomUserDetailsService类,

实现AuthenticationUserDetailsService

package com.jeeplus.security.service;

import com.jeeplus.core.errors.ErrorConstants;
import com.jeeplus.sys.constant.CommonConstants;
import com.jeeplus.sys.service.UserService;
import com.jeeplus.sys.service.dto.UserDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.*;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 用于加载用户信息
 * @author: 王强
 * @create: 2023-04-20 10:40
 **/
public class CustomUserDetailsService implements AuthenticationUserDetailsService<CasAssertionAuthenticationToken> {
    @Autowired
    private UserService userService;


    /**
     * 当cas登录成功后会进入到这里
     * @param token
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserDetails(CasAssertionAuthenticationToken token) throws UsernameNotFoundException {
        System.out.println(token.getName());
        return new User(token.getName(), "", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));

    }
}

四:创建security配置类

package com.jeeplus.security.config;

import com.jeeplus.security.exception.JwtAccessDeniedHandler;
import com.jeeplus.security.exception.JwtAuthenticationEntryPoint;
import com.jeeplus.security.jwt.JWTConfigurer;
import com.jeeplus.security.jwt.TokenProvider;
import com.jeeplus.security.service.CustomUserDetailsService;
import com.jeeplus.security.util.DaoAuthenticationProvider;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法级安全验证
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//    @Autowired
//    private CustomUserDetailsService userDatailService;
    @Autowired
    private  JwtAuthenticationEntryPoint unauthorizedHandler;
    @Autowired
    private JwtAccessDeniedHandler accessDeniedHandler;

    @Autowired
    private CasProperties casProperties;

    /**
     * 描述:设置授权处理相关的具体类以及加密方式
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
        auth.authenticationProvider(casAuthenticationProvider());
//        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
//        // 设置不隐藏 未找到用户异常
//        provider.setHideUserNotFoundExceptions(true);
//        // 用户认证service - 查询数据库的逻辑
//        provider.setUserDetailsService(userDetailsService());
//        // 设置密码加密算法
//        provider.setPasswordEncoder(passwordEncoder());
//        provider.setUserDetailsService ( userDatailService );
//        auth.authenticationProvider(provider);
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        http.authorizeRequests()//配置安全策略
//                .antMatchers("/", "/hello").permitAll()//定义请求不需要验证
//            .anyRequest().authenticated()//其余的所有请求都需要验证
//            .and().logout().permitAll()//定义logout不需要验证
//            .and().formLogin();//使用form表单登录

            http
                .headers().frameOptions().disable ().and ()
                .exceptionHandling().accessDeniedHandler(accessDeniedHandler).and()
                // 由于使用的是JWT,我们这里不需要csrf
                .csrf().disable()
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                // 基于token,所以不需要session
//                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                .antMatchers ( "/401"
                        ,"/404",
                        "/app/rest/**",
                        "/druid/**",
                        "/v1/**",
                        "/v2/**",
                        "/weboffice/**",
                        "/ReportServer/**",
                        "/sys/login",
                        "/app/sys/login",
                        "/sys/sysConfig/getConfig",
                        "/getAppFlowChart",
                        "/sys/getCode",
                        "/sys/getLoginCodeNumber",
                        "/cwProjectReport/signatureCallBack/**",
                        "/app/sys/getCode",
                        "/sys/casLogin",
                        "/hello",
                        "/app/luckyDraw/**",
                        "/sys/saveNewPassword",
                        "/sys/getPhoneCode").permitAll() // 允许请求无需认证
                .antMatchers( HttpMethod.OPTIONS, "/**").permitAll()
                .anyRequest().authenticated(); // 所有请求都需要验证
//                .and ()
//                .apply(securityConfigurerAdapter());

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

    }

    /**
     * 描述: 静态资源放行,这里的放行,是不走 Spring Security 过滤器链
     **/
    @Override
    public void configure(WebSecurity web) {
        // 可以直接访问的静态数据
        web.ignoring()
                .antMatchers(
                        "/doc.html",
                        "/swagger-ui.html",
                        "/userfiles/**",
                        "/static/**",
                        "/swagger**/**",
                        "/webjars/**");
    }

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

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

    /**CAS认证过滤器*/
    @Bean
    public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
        CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
        casAuthenticationFilter.setAuthenticationManager(authenticationManager());
        casAuthenticationFilter.setFilterProcessesUrl(casProperties.getAppLoginUrl());
        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());
    }

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

    /**请求单点退出过滤器*/
    @Bean
    public LogoutFilter casLogoutFilter() {
        LogoutFilter logoutFilter = new LogoutFilter(casProperties.getCasServerLogoutUrl(), new SecurityContextLogoutHandler());
        logoutFilter.setFilterProcessesUrl(casProperties.getAppLogoutUrl());
        return logoutFilter;
    }

    /**
     * 描述: 密码加密算法 BCrypt 推荐使用
     **/
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 描述: 注入token
     **/
    @Bean
    public TokenProvider tokenProvider() {
        return new TokenProvider ();
    }

    private JWTConfigurer securityConfigurerAdapter() throws Exception{
        return new JWTConfigurer(tokenProvider () , authenticationManager ());
    }

    /**
     * 描述: 注入AuthenticationManager管理器
     **/
    @Override
    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }
}

建议根据项目对代码进行修改

参考

https://www.jb51.net/article/114678.htm

https://blog.csdn.net/cheng137666/article/details/110224088

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值