0
点赞
收藏
分享

微信扫一扫

174-ruoyi-cloud整合cas-server5.3(2)-auth模块的修改

platform-auth/pom.xml引入jar:

<dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-cas</artifactId>
            <version>5.0.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

bootstrap-test.yml 配置:

server:
  port: 10002
app:
  login:
    url: /login
  logout:
    url: /casLogout
  server:
    host:
      url: http://localhost:10002
  uiUrl: http://localhost:80

cas:
  enable: true
  server:
    host:
      login_url: ${cas.server.host.url}/login
      logout_url: ${cas.server.host.url}/logout?service=${app.uiUrl}
      url: http://localhost:8080/cas

TokenController.java新增cas登录:

@ConditionalOnProperty(prefix = "cas",name = "enable",havingValue = "true")
    @GetMapping("casLogin")
    public AjaxResult casLogin()
    {
        UserDetails loginUser=(UserDetails) CasSecurityUtils.getLoginUser();
        AjaxResult ajax = AjaxResult.success();
        LoginUser userInfo = sysLoginService.login(loginUser.getUsername());
        Map<String, Object> tokenMap = tokenService.createToken(userInfo,1);
        ajax.put("user", userInfo.getSysUser());
        ajax.put("roles", userInfo.getRoles());
        ajax.put("permissions", userInfo.getPermissions());
        ajax.put("token",tokenMap.get("access_token"));
        return ajax;
    }

新增CAS的配置参数: CasProperties.java

/**
 * CAS的配置参数
 * @author cjq
 */
@Component
public class CasProperties {
    @Value("${cas.enable:false}")
    private boolean enable;
    @Value("${cas.server.host.url:}")
    private String casServerUrl;

    @Value("${cas.server.host.login_url:}")
    private String casServerLoginUrl;

    @Value("${cas.server.host.logout_url:}")
    private String casServerLogoutUrl;

    @Value("${app.server.host.url:}")
    private String appServerUrl;

    @Value("${app.login.url:}")
    private String appLoginUrl;

    @Value("${app.logout.url:}")
    private String appLogoutUrl;
    @Value("${app.uiUrl:}")
    private String uiUrl;
    //get/set省略
}

用于加载用户信息 实现UserDetailsService接口,或者实现AuthenticationUserDetailsService接口:


/**
 * 用于加载用户信息 实现UserDetailsService接口,或者实现AuthenticationUserDetailsService接口
 *
 * @author cjq
 */
public class CustomUserDetailsService implements AuthenticationUserDetailsService<CasAssertionAuthenticationToken> {

    private static final Logger log = LoggerFactory.getLogger(CustomUserDetailsService.class);

    /**
     * 加载登录用户的信息
     *
     * @param token
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserDetails(CasAssertionAuthenticationToken token) throws UsernameNotFoundException {
        System.out.println("当前的用户名是:" + token.getName());
        String username = token.getName();
        return new User(username,"",new HashSet<>());
    }

}

启动类AuthApplication.java 修改: 新增成员:

@Autowired
    private CasProperties casProperties;

新增重定向:

@CrossOrigin
    @RequestMapping("/")
    @ConditionalOnProperty(prefix = "cas",name = "enable",havingValue = "true")
    public void index(HttpServletResponse response) throws IOException {
        System.out.println("-----------"+response.getStatus());
        response.sendRedirect(casProperties.getUiUrl());
    }

退出登录处理:


/**
 * 退出登录处理
 *
 * @author cjq
 * @date 2022/11/4
 */
@Configuration
public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler {

    @Autowired
    private SysLoginService sysLoginService;
    @Autowired
    private CasProperties casProperties;
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        String token = SecurityUtils.getToken(request);
        if (StringUtils.isNotEmpty(token))
        {
            String username = JwtUtils.getUserName(token);
            // 删除用户缓存记录
            AuthUtil.logoutByToken(token);
            // 记录用户退出日志
            sysLoginService.logout(username);
        }
        ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.success("退出成功",casProperties.getCasServerLogoutUrl())));
    }
}

CasSecurityUtils工具类:


/**
 * desc
 *
 * @author cjq
 * @date 2022/11/4
 */
public class CasSecurityUtils {
    /**
     * 获取用户
     **/
    public static Object getLoginUser()
    {
        try
        {
            return  getAuthentication().getPrincipal();
        }
        catch (Exception e)
        {
            throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
        }
    }

    /**
     * 获取Authentication
     */
    public static Authentication getAuthentication()
    {
        return SecurityContextHolder.getContext().getAuthentication();
    }

}

认证失败处理类,返回未授权:


/**
 * 认证失败处理类 返回未授权
 *
 * @author cjq
 */
@ConditionalOnProperty(prefix = "cas",name = "enable",havingValue = "true")
@Component
public class CASAuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable
{
    private static final long serialVersionUID = -8970718410437077606L;

    @Autowired
    private CasProperties casProperties;

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e)
            throws IOException
    {
        StringBuffer requestURL = request.getRequestURL();
        int code = HttpStatus.UNAUTHORIZED;
        String msg = StringUtils.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI());
        AjaxResult error = AjaxResult.error(code, msg);
        error.put("loginUrl",casProperties.getCasServerLoginUrl()+"?service="+casProperties.getAppServerUrl() + casProperties.getAppLoginUrl());
        ServletUtils.renderString(response, JSON.toJSONString(error));
    }
}

CasSecurityConfig.java:


@ConditionalOnProperty(prefix = "cas",name = "enable",havingValue = "true")
@Configuration
@EnableWebSecurity //启用web权限
@EnableGlobalMethodSecurity(prePostEnabled = true) //启用方法验证
public class CasSecurityConfig extends WebSecurityConfigurerAdapter {

    private static final Logger log = LoggerFactory.getLogger(CasSecurityConfig.class);

    @Autowired
    private CasProperties casProperties;
    @Autowired
    private LogoutSuccessHandlerImpl logoutSuccessHandler;

    /**
     * 认证失败处理类
     */
    @Autowired
    private CASAuthenticationEntryPointImpl unauthorizedHandler;

    /**
     * 解决 无法直接注入 AuthenticationManager
     *
     * @return
     * @throws Exception
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * 定义认证用户信息获取来源,密码校验规则等
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
        if(casProperties.getEnable()==true){
            auth.authenticationProvider(casAuthenticationProvider());
        }
    }

    /**
     * 定义安全策略
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        String[] permitAll = new String[]{"/login", "/captchaImage"};
        String[] staticMatchers = new String[]{"/*.html",
                "/**/*.html",
                "/**/*.css",
                "/**/*.js",
                "/"};
        String[] anonymous = new String[]{"/profile/**","/common/download**",
                "/common/download/resource**","/swagger-ui.html",
                "/swagger-resources/**","/webjars/**",
                "/*/api-docs","/druid/**","/modeler/**",
                "/activiti/definition/upload",
                "/activiti/definition/readResource",
                "/activiti/process/read-resource"};
        boolean casEnable = casProperties.getEnable();
        http.csrf().disable()
                // 认证失败处理类
                .authorizeRequests()//配置安全策略
                .antMatchers(permitAll).permitAll()
                .antMatchers(
                        HttpMethod.GET,
                        staticMatchers
                ).permitAll()
                .antMatchers(anonymous).anonymous()
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated().and()
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                .addFilter(casAuthenticationFilter())
                .addFilterBefore(casLogoutFilter(), LogoutFilter.class)
                .addFilterBefore(singleSignOutFilter(), CasAuthenticationFilter.class);

    }

    /**
     * 认证的入口
     */
    @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.setServiceProperties(serviceProperties());
        casAuthenticationProvider.setTicketValidator(cas20ServiceTicketValidator());
        casAuthenticationProvider.setKey("casAuthenticationProviderKey");
        return casAuthenticationProvider;
    }

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

    /**
     * 配置ticket校验器
     *
     * @return
     */
    @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(logoutSuccessHandler,new SecurityContextLogoutHandler());
        logoutFilter.setFilterProcessesUrl(casProperties.getAppLogoutUrl());
        return logoutFilter;
    }

}

NotCasSecurityConfig.java:


@ConditionalOnProperty(prefix = "cas",name = "enable",havingValue = "false")
@Configuration
@EnableWebSecurity //启用web权限
@EnableGlobalMethodSecurity(prePostEnabled = true) //启用方法验证
public class NotCasSecurityConfig extends WebSecurityConfigurerAdapter {

    private static final Logger log = LoggerFactory.getLogger(NotCasSecurityConfig.class);

    @Autowired
    private LogoutSuccessHandlerImpl logoutSuccessHandler;

    /**
     * 定义认证用户信息获取来源,密码校验规则等
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
    }

    /**
     * 定义安全策略
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        String[] permitAll = new String[]{"/login", "/captchaImage","logout"};
        String[] staticMatchers = new String[]{"/*.html",
                "/**/*.html",
                "/**/*.css",
                "/**/*.js",
                "/"};
        String[] anonymous = new String[]{"/profile/**","/common/download**",
                "/common/download/resource**","/swagger-ui.html",
                "/swagger-resources/**","/webjars/**",
                "/*/api-docs","/druid/**","/modeler/**",
                "/activiti/definition/upload",
                "/activiti/definition/readResource",
                "/activiti/process/read-resource"};
        http.csrf().disable()
                // 认证失败处理类
                .authorizeRequests()//配置安全策略
                .antMatchers(permitAll)
                .permitAll()
                .antMatchers(HttpMethod.GET, staticMatchers)
                .permitAll()
                .antMatchers(anonymous)
                .anonymous()
                .anyRequest()
                .anonymous()
                .and().logout().logoutSuccessHandler(logoutSuccessHandler);

    }


}
举报

相关推荐

0 条评论