cas 单点登陆实战-sso-config篇(五)

2023-05-16

 

本篇我们讲解cas单点登陆在与shiro集成,在与redis集成遇到的问题

先看完整代码吧



package com.madnet.config;


import com.google.common.base.CaseFormat;
import com.madnet.module.permission.repository.PermissionRepository;
import com.madnet.module.permission.service.PermissionService;
import io.buji.pac4j.filter.CallbackFilter;
import io.buji.pac4j.filter.LogoutFilter;
import io.buji.pac4j.filter.SecurityFilter;
import io.buji.pac4j.realm.Pac4jRealm;
import io.buji.pac4j.subject.Pac4jSubjectFactory;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.AbstractShiroWebFilterConfiguration;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.jasig.cas.client.authentication.AuthenticationFilter;
import org.pac4j.cas.client.CasClient;
import org.pac4j.cas.client.rest.CasRestFormClient;
import org.pac4j.cas.config.CasConfiguration;
import org.pac4j.cas.config.CasProtocol;
import org.pac4j.core.client.Clients;
import org.pac4j.core.config.Config;
import org.pac4j.core.matching.PathMatcher;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import java.awt.*;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.shiro.cas.CasFilter;
import org.crazycake.shiro.RedisCacheManager;

/**
 * 对shiro的安全配置,是对cas的登录策略进行配置
 *
 * @author Carl
 * @date 2017/9/16
 * @since 1.0.0
 */
@Configuration
public class ShiroConfiguration extends AbstractShiroWebFilterConfiguration {
    @Value("#{ @environment['cas.prefixUrl'] ?: null }")
    private String prefixUrl;
    @Value("#{ @environment['cas.loginUrl'] ?: null }")
    private String casLoginUrl;
    @Value("#{ @environment['cas.callbackUrl'] ?: null }")
    private String callbackUrl;
    @Value("#{ @environment['cas.serviceUrl'] ?: null }")
    private String serviceUrl;
    @Autowired
    private PermissionService permissionService;

    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.timeout}")
    private String timeout;


    /**
     * cas核心过滤器,把支持的client写上,filter过滤时才会处理,clients必须在casConfig.clients已经注册
     *
     * @return
     */
    @Bean
    public Filter casSecurityFilter() {
        SecurityFilter filter = new SecurityFilter();
        filter.setClients("cas,rest");
        filter.setConfig(casConfig());
        return filter;
    }


    /**
     * 通过rest接口可以获取tgt,获取service ticket,甚至可以获取CasProfile
     *
     * @return
     */
    @Bean
    protected CasRestFormClient casRestFormClient() {
        CasRestFormClient casRestFormClient = new CasRestFormClient();
        casRestFormClient.setConfiguration(casConfiguration());
        casRestFormClient.setName("rest");
        return casRestFormClient;
    }

    @Bean
    public PathMatcher pathMatcher() {
        PathMatcher pathMatcher = new PathMatcher();
        pathMatcher.excludePath("/**");
        return pathMatcher;
    }

    @Bean
    protected Clients clients() {
        //可以设置默认client
        Clients clients = new Clients();
        //支持的client全部设置进去
        clients.setClients(casClient(), casRestFormClient());
        return clients;
    }

    @Bean
    public CasClient casClient() {
        CasClient casClient = new CasClient();
        casClient.setConfiguration(casConfiguration());
        casClient.setCallbackUrl(callbackUrl);
        casClient.setName("cas");
        return casClient;
    }

    @Bean
    protected Config casConfig() {
        Config config = new Config();
        config.setClients(clients());

        return config;
    }

    /**
     * cas的基本设置,包括或url等等,rest调用协议等
     *
     * @return
     */
    @Bean
    public CasConfiguration casConfiguration() {
        CasConfiguration casConfiguration = new CasConfiguration(casLoginUrl);
        casConfiguration.setProtocol(CasProtocol.CAS30);
        casConfiguration.setPrefixUrl(prefixUrl);
        return casConfiguration;
    }




    /**
     * 路径过滤设置
     *
     * @return
     */
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
        definition.addPathDefinition("/login2", "casSecurityFilter");
        definition.addPathDefinition("/login.jsp", "casSecurityFilter");
        definition.addPathDefinition("/callback", "callbackFilter");
        definition.addPathDefinition("/logout", "logoutFilter");

        return definition;
    }




    @Bean
    protected Map<String, Filter> shiroFilters() {
        //过滤器设置
        Map<String, Filter> filters = new HashMap<>();

        filters.put("casSecurityFilter", casSecurityFilter());

        CallbackFilter callbackFilter = new CallbackFilter();
        callbackFilter.setConfig(casConfig());
        filters.put("callbackFilter", callbackFilter);

        LogoutFilter logoutFilter = new LogoutFilter();
        logoutFilter.setConfig(casConfig());
        logoutFilter.setCentralLogout(true);
        logoutFilter.setDefaultUrl(serviceUrl);
        filters.put("logoutFilter", logoutFilter);



        return filters;
    }

    @Bean
    public Realm pac4jRealm() {
        return new RealmConfiguration();
    }




    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setSubjectFactory(new Pac4jSubjectFactory());
        securityManager.setRealm(pac4jRealm());
      //  securityManager.setSessionManager(SessionManager());
       // securityManager.setCacheManager(cacheManager());
        return securityManager;
    }



    @Bean(name = "casFilter")
    public CasFilter getCasFilter() {
        CasFilter casFilter = new CasFilter();
        casFilter.setName("casFilter");
        casFilter.setEnabled(true);
        casFilter.setLoginUrl("/login2");
        // 登录失败后跳转的URL,也就是 Shiro 执行 CasRealm 的 doGetAuthenticationInfo 方法向CasServer验证tiket
        casFilter.setFailureUrl(loginUrl);// 我们选择认证失败后再打开登录页面


        return casFilter;
    }



    /**
     * 对过滤器进行调整
     *
     * @return
     */
    @Bean("shiroFilter")
    protected ShiroFilterFactoryBean shiroFilterFactoryBean() {

        ((DefaultSecurityManager) securityManager).setSubjectFactory(new Pac4jSubjectFactory());

        ShiroFilterFactoryBean filterFactoryBean = super.shiroFilterFactoryBean();
        filterFactoryBean.setSecurityManager(securityManager);
        filterFactoryBean.setFilters(shiroFilters());


        Map<String, String> initParameters = new HashMap();
        initParameters.put("/callback","callbackFilter");
        initParameters.put("/logout","logoutFilter");
       // initParameters.put("/upload.html", "casSecurityFilter");
        initParameters.put("/static/**", "anon");
        initParameters.put("/upload.html", "authc");
        initParameters.putAll(permissionService.getAuthcMap());

        filterFactoryBean.setFilterChainDefinitionMap(initParameters);

        filterFactoryBean.setLoginUrl("/login2");
        // 登录成功后要跳转的链接
        filterFactoryBean.setSuccessUrl("/index.html");
        // 未授权界面;
        filterFactoryBean.setUnauthorizedUrl("/login2");

        return filterFactoryBean;
    }



    /**
     * 对shiro的过滤策略进行明确
     *
     * @return
     */

    @Bean
    public FilterRegistrationBean delegatingFilterProxy() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        DelegatingFilterProxy proxy = new DelegatingFilterProxy();
        proxy.setTargetFilterLifecycle(true);
        proxy.setTargetBeanName("shiroFilter");
        filterRegistrationBean.setFilter(proxy);

        return filterRegistrationBean;
    }


    /**
     * 开启 shiro aop注解支持
     *
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
        aasa.setSecurityManager(securityManager);
        return aasa;
    }

    @Bean
    public FilterRegistrationBean someFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(casSecurityFilter());
        registration.addUrlPatterns("/login2");
        registration.setName("casSecurityFilter");
        return registration;


    }


    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }


    /**
     * 配置shiro redisManager
     *
     * @return
     */
    @Bean
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(host);
        redisManager.setPort(port);
        redisManager.setExpire(18000);// 配置过期时间
         //redisManager.setTimeout(Integer.parseInt(timeout));
        // redisManager.setPassword(String.valueOf(password));

        return redisManager;
    }

    /**
     * cacheManager 缓存 redis实现
     *
     * @return
     */
    @Bean(name="cach")
    public RedisCacheManager cacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());

        return redisCacheManager;
    }

    /**
     * RedisSessionDAO shiro sessionDao层的实现 通过redis
     */
    @Bean
    public RedisSessionDAO redisSessionDAO() {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        return redisSessionDAO;
    }


    /**
     * shiro session的管理
     */
    @Bean
    public DefaultWebSessionManager SessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        //sessionManager.setSessionIdCookie(sessionMeCookie());
        sessionManager.setSessionDAO(redisSessionDAO());

        return sessionManager;
    }
    @Bean
    public SimpleCookie sessionMeCookie() {
        SimpleCookie simpleCookie = new SimpleCookie("madnet-s-org");
        simpleCookie.setMaxAge(-1);
        simpleCookie.setDomain(".mad-net.org");
        return simpleCookie;
    }

    @Bean
    public SimpleCookie rememberMeCookie() {
        // 这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("madnet-re-org");
        simpleCookie.setMaxAge(18000);
        // <!-- 记住我cookie生效时间30天 ,单位秒;-->
//		simpleCookie.setMaxAge(2592000);
        simpleCookie.setDomain(".mad-net.org");
        return simpleCookie;
    }


}
cas:
    prefixUrl: https://172.17.1.10:8443/cas
    loginUrl: ${cas.prefixUrl}/login
    serviceUrl: http://172.17.1.10:${server.port}
    callbackUrl: ${cas.serviceUrl}/callback

jwt:
    salt: 12345678901234567890123456789012
debug: true

若想同时使用

setFilterChainDefinitionMap 和
setFilters

你一定要把规则写到setFilterChainDefinitionMap这个方法中,具体方法看代码吧

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

cas 单点登陆实战-sso-config篇(五) 的相关文章

  • R 单因素logistic回归

    单因素logistic回归 logitUniVar span class token operator lt span span class token keyword function span span class token punc
  • ubuntu 22.04修改时区 让date显示以24小时格式显示

    先记录一下我为什么要关注我设备的时区和时间显示方法 xff1b 我原本想在我的服务器上做几个定时的监控任务 xff08 crontab 任务 xff09 xff0c 但是在我测试我任务的时候总是不能按照系统时间进行执行 xff08 我通过d
  • 针对字节流中的传输中的强制类型转换和memcpy的区别

    举个栗子 xff1a memcpy amp b amp a sizeof b 这个是从b的地址开始 xff0c 复制sizeof b 那么多的东西到a指向的内存 b 61 char a 这个是截取a的低八位给b赋值
  • 海龟交易法则 读书笔记

    交易的世界里面 保命第一 打赢谁 在打谁 做有把握的事情 1 xff1a 新手交易最好采用保守一点的交易策略 2 xff1a 每笔交易的风险投入达到了交易资本的3 破产风险很大 3 xff1a 衰落幅度最好不要超过承受上限的50
  • PyQt中为什么QActino在连接信号与槽的代码中出发创建知识就被触发

    原来的语句 xff0c 会出现这个问题 Select Strategy action triggered connect self Run Stratgy xff08 xff09 把Run Strategy括号去掉就行了 Select St
  • 《深度探究C++对象模型》笔记

    typdef span class token keyword int span lenght span class token keyword class span span class token class name A span s
  • 基金理财语录

    1 xff1a 理财不是发财 2 xff1a 市场的走势和我们的意愿无关 3 xff1a 不当抱死一只基金 一支基金长期业绩不行就是不行 4 xff1a 最好是用红利再投资 5 xff1a 不是市场有了巨变 xff0c 而是人心发生了转变
  • 《时间管理机》笔记

    1 xff1a 实践是检验真理的一切标准 2 xff1a 时间管理是一种生活方式 xff0c 是一种习惯 3 xff1a 或许你对写报告时候聊3分钟QQ或者微信或者刷微博不以为然 xff0c 但是我要告诉你 xff0c 曾经有人做过这样的实
  • Unix Shell中单引号、双引号字符、反斜杠、反引号的使用

    在执行shell脚本的时候 xff0c shell将会对脚本中的行进行解释 xff0c 然后执行 xff1b 对于一些特殊处理的句子 xff0c 我们可以使用引号或者反斜线来避免shell解释执行之 如下 xff0c 当在命令行中输入 xf
  • 我的基金组合和选择标准

    基金组合 xff1a 注意 xff1a 自己的基金投资组合每半年和一年做一次审查 xff0c 定投基金就要有长期投资的准备 xff0c 要有长期标的 xff0c 如果基金业绩不好很长时间就要放弃 xff0c 赚钱才是第一 xff0c 选择中
  • 股票

    选股 xff1a 一般大牛股都要早于大盘开始拉升 市盈率要低于20算低估 最好是低于10 要找次新股 xff0c 最好不要分红除权过后的股票 有行情的时候 xff0c 可以选择宽基指数基金 xff0c 快进快出 如沪深300 牛市使劲买 x
  • 《亲密关系》读书笔记

    1 xff1a 对家庭死忠 xff1a 对家庭成员的模仿塑造了自我 xff0c 而丢失了自我 xff0c 在面对亲密关系的时候 xff0c 我们需要找到自己灵魂内心最真实的感受 xff0c 而不是固守成规 xff0c 模仿家中 xff0c
  • 价差交易

    1 xff1a 尽量瞄准价差变化大得时候开仓 2 xff1a 在升水价差时期 xff0c 价差在扩大之后 xff0c 常常会收敛回到前面得波谷得地方 3 xff1a 价差有风险 xff0c 学会资金管理 xff0c 要学会止损 4 xff1
  • 天勤开发介绍

    5 回测暂不支持 获取多合约K线 若在回测时获取多合约K线 xff0c 程序会报出获取数据超时异常
  • linux下C++如何连接mysql数据库

    在Linux下 xff0c 我们可以通过MySQL提供的C API连接数据库 使用C API连接mysql数据库除了要安装mysql client和mysql server xff0c 还需要安装mysql的开发包mysql devel 我
  • Qt5安装mysql驱动

    转载 xff1a https blog csdn net D759378563 article details 77720830 utm medium 61 distribute pc relevant none task blog Blo
  • Qt Creator报错无法引用某个库函数的问题

    target link libraries detector nvinfer nvinfer plugin nvparsers OpenCV LIBS 34 stdc 43 43 fs 34 今天编译一个开源库 xff0c 用cmake构建
  • Qt在使用QMap时候出现mumap_chunk():invalid pointer问题

    之前用Qt开发了一个上位机软件 xff0c 在移植到树莓派4的时候出现了问题 xff0c 软件运行报错 xff1a mumao chunk invalid pointer 在调试发现是在使用QMap的T amp const key 时候 问
  • ubuntu下 QT 连接sqlite数据库报错问题一招解决(QSqlDatabase: * driver not loaded )

    sudo apt get install libqt5 把所有的qt5库都装上 xff0c 就是干 xff01 参考博客 xff1a ubuntu下 QT 连接各种数据库报错解决 xff08 QSqlDatabase driver not
  • 零基础入门无人机--无人机姿态--2

    四旋翼在其四个轴臂上四个桨的高速转动作用下 xff0c 会受到四个桨的拉力 xff0c 拉力方向与机身垂直 xff0c 当四个桨产生的拉力总和大于机身重力时 xff0c 飞机处于上升状态 xff1b 当总拉力小于机身重力时 xff0c 飞机

随机推荐