版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_37797991/article/details/78529096
前言
shiro是一个非常强大的权限管理框架,关于shiro与cas整合的示例有很多,但是我们平时开发的时候,很多公司并不是使用cas来做SSO的,而是自己公司会用自己开发的。本文就主要针对这种方式的整合。

新增SSO相关的properties
#sso服务器登录地址,service参数表示登录成功后要跳转的地址
ssoServiceUrl=http://www.authserver.com/auth/login?service=http://www.client.com/user/login

#sso的token的校验地址
tokenValidateUrl=http://www.authserver.com:9999/auth/validatetoken

#应用名称标识
microServiceId=app

#redis相关信息
JedisUrl=198.168.1.101
JedisPort=6379
JedisPassword=666666
1
2
3
4
5
6
7
8
9
10
11
12
13
修改spring-shiro.xml
<bean id="shiroSecurityFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
   <property name="securityManager" ref="securityManager" />
   <property name="loginUrl" value="${ssoServiceUrl}" />
   <!-- <property name="successUrl" value="/user/index" /> -->
   <property name="filters">
           <map>
               <entry key="authc" value-ref="ssoFilter"/>
           </map>
   </property>
   <property name="filterChainDefinitions">
      <value>
         /kaptcha.jpg=anon
         /assets/** = anon
         /images/** = anon
         /javascripts/** = anon
         /stylesheets/** = anon
         /user/login = anon
         /httpserver/* = anon
         /** = authc
      </value>
   </property>
</bean>
<bean id="ssoFilter" class="com.demo.web.sso.SSOFilter"/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
自定义ssoFilter
/**
 * sso自定义过滤器
 */
public class SSOFilter implements Filter{

public void init(FilterConfig filterConfig) throws ServletException {
    }

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        {
            HttpServletRequest request = (HttpServletRequest)servletRequest;
            HttpServletResponse response = (HttpServletResponse)servletResponse;
            String token = request.getParameter("token");
            PropertiesTool propertiesTool = PropertiesTool.getInstance();
            String ssoServiceUrl = propertiesTool.getValue("ssoServiceUrl");
            String tokenValidateUrl = propertiesTool.getValue("tokenValidateUrl");
            if(null == token) {
                Cookie cookie = CookieUtil.getCookieByName(request, "token");
                if(null != cookie) {
                    token = cookie.getValue();
                }
            }
            if(null == token) {
                //没有token,重定向至sso server登录页
                response.sendRedirect(ssoServiceUrl);
            }else {
                String urlString = request.getRequestURI();
                if(urlString.endsWith("/logout")) {
                    String JedisUrl = propertiesTool.getValue("JedisUrl");
                    String JedisPort = propertiesTool.getValue("JedisPort");
                    Jedis jedis = new Jedis(JedisUrl, Integer.parseInt(JedisPort));
                    jedis.del(token.getBytes());
                    jedis.close();
                    SecurityUtils.getSubject().logout();
                    response.sendRedirect(ssoServiceUrl);//重定向至sso server登录页
                    return;
                }

//有token,去sso server验证token的有效性
                Map<String, String> map = new HashMap<>();
                map.put("token", token);
                String result = HttpClientUtil.doGet(tokenValidateUrl, map);
                if(StringUtils.isNotBlank(result)){//验证成功,跳转至首页,并从redis中获取权限
                    SystemSession.setUser(SSOTokenUtil.getToken(request));//设置系统session(把用户信息保存在ThreadLocal中)
                    Cookie cookie = new Cookie("token", token);
                    cookie.setPath("/");
                    response.addCookie(cookie);
                    filterChain.doFilter(request, response);
                } else{
                    response.sendRedirect(ssoServiceUrl);//验证失败,重定向至sso server登录页
                }
            }
        }
    }

public void destroy() {

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
自定义shiro的realm
在spring-shiro.xml中添加:

<bean id="myRealm" class="com.demo.web.realm.MyRealm"/>
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="realm" ref="myRealm" />
    </bean>

<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
    <bean
        class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager" />
    </bean>
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
    </bean>
1
2
3
4
5
6
7
8
9
10
11
12
realm类:

public class MyRealm extends AuthorizingRealm{

public MyRealm() {
        setName("myRealm");
        HashedCredentialsMatcher hcm = new HashedCredentialsMatcher();
        //使用SHA-512 加密
        hcm.setHashAlgorithmName(Sha512Hash.ALGORITHM_NAME);
        setCredentialsMatcher(hcm);
    }

@Override
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {
        SysUser user = SystemSession.getUser();
        if (user != null) {
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            List<Menu> list = user.getRoles().get(0).getMenuList();
            for (Menu menu : list){
                if (StringUtils.isNotBlank(menu.getPermission())) {
                    // 添加基于Permission的权限信息
                    for (String permission : StringUtils.split(menu.getPermission(),",")){
                        info.addStringPermission(permission);
                    }
                }
            }
            // 添加用户权限
            info.addStringPermission("user");
            // 添加用户角色信息
            for (SysRole role : user.getRoles()) {
                info.addRole(role.getEnglishName());
            }
            return info;
        } else {
            return null;
        }
    }

@Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken authcToken) throws AuthenticationException {
        //获取user信息
        SysUser user = SystemSession.getUser();
        if (user != null) {
            if (user.getIsEnable()!=1) {
                throw new AuthenticationException("msg:该帐号已禁止登录.");
            }
            return new SimpleAuthenticationInfo(new Principal(user), Constants.CREDENTIALS, getName());
        }
        return null;
    }

public static class Principal implements Serializable {

private static final long serialVersionUID = 1L;

private String id; // 编号
        private String loginName; // 登录名
        private String name; // 姓名
        private List<String> roleIdList;

public List<String> getRoleIdList() {
            return roleIdList;
        }

public void setRoleIdList(List<String> roleIdList) {
            this.roleIdList = roleIdList;
        }

public Principal(SysUser user) {
            this.id = user.getId();
            this.loginName = user.getUsername();
            this.name = user.getCharacterName();
            this.roleIdList=user.getRoleIdList();
        }

public String getId() {
            return id;
        }

public String getLoginName() {
            return loginName;
        }

public String getName() {
            return name;
        }

@Override
        public String toString() {
            return id;
        }

}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
由于shrio权限要做登录校验,但我们的登录已交给sso处理,这里只需要保证shiro的前后校验能通过就行,把password改成常量,并取消原来的加盐。CREDENTIALS=”6bf968f0c7b39ddbb7c8aa836b74d092060ed9b85b620a7fb088ecc48c6b3efd696bbd820f74c14f66c80c86c557c4bfda51b8a3743d3d568cc5c08410b7bb6a”;

修改index
@RequestMapping("index")
public String index(ModelMap model, String mainFrame, HttpServletRequest request) {
       SysUser currentUser = SSOTokenUtil.getToken(request);
   List<Menu> menus = currentUser.getRoles().get(0).getMenuList();
   List<Menu> sysMenus = new ArrayList<>();
   for(Menu menu : menus){
      if(currentUser.getRemarks().equals(menu.getSysCode())){
         sysMenus.add(menu);
      }
   }
   //设置用户登录信息
   UsernamePasswordToken token = new UsernamePasswordToken(
         currentUser.getUsername(), Constants.PASSWORD);
   SecurityUtils.getSubject().login(token);
   model.addAttribute("menus", sysMenus);
   model.addAttribute("currentUser", currentUser);

return "index";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
PASSWORD= “lvadmin”,是CREDENTIALS对应的明文。

文中所用到的一些SSOFilter,SystemSession,SSOTokenUtil等原码,以附件的形式提供下载。 
Shiro整合SSO单点登录系统工具类下载
 ———————————————— 
版权声明:本文为CSDN博主「MrCao杰罗尔德」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_37797991/article/details/78529096

Shiro整合SSO单点登录系统相关推荐

  1. SpringBoot+MyBatis+Redis实现SSO单点登录系统(二)

    SpringBoot+MyBatis+Redis实现SSO单点登录系统(二) 三.代码 配置文件配置数据库,redis等相关的信息. # See http://docs.spring.io/sprin ...

  2. SpringBoot+MyBatis+Redis实现SSO单点登录系统(一)

    SpringBoot+MyBatis+Redis实现SSO单点登录系统(一) 一.SSO系统概述 SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可 ...

  3. sso单点登录系统(解决session共享)

    场景:假设一个用户将自己的登录信息提交到后台,如果session保存的信息分布在多台机器上,并且不共享,那么可能导致用户的登录信息出现短暂的丢失,为什么这样讲,因为用户访问服务器中间还要经过负载均衡服 ...

  4. 互联网分布式微服务云平台规划分析--SSO单点登录系统

    介绍 鸿鹄云架构[SSO单点登录系统]为所有微服务提供统一的用户认证服务,系统本身属于微服务模式,使用JWT+Redis分布式存储方案,确保不同微服务.系统之间的安全通讯和统一用户校验.认证.在整个服 ...

  5. 手撕一套sso(单点登录)系统之原理篇1

    在手撕之前,你首先要了解一些原理,我写的案例成品可以访问zauth,语言是Java8. 目录 1.关于Http 2.用户信息怎么存?存什么?存在哪? 2.1 使用前端存储技术Storage或index ...

  6. JWT实战 Spring Security Oauth2整合JWT 整合SSO单点登录

    文章目录 一.JWT 1.1 什么是JWT 1.2 JWT组成 头部(header) 载荷(payload) 签名(signature) 如何应用 1.3 JJWT 快速开始 创建token toke ...

  7. SSO单点登录系统的实战运用

    通用介绍 单点登录系统,简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.任何SSO框架都需要创建统一的认 ...

  8. sso单点登录系统的理解

    单点登录有两种方式,一种是跨域,一种是不跨域. 一:在不跨域的情况下, 只需要将cookie设置为顶域状态,即可以实现cookie的共享. 二:跨域登录 用户访问app系统,app系统是需要登录的,但 ...

  9. 基于cookie的SSO单点登录系统

    利用COOKIE实现单点登录功能 近期公司要求帮一个项目实现单点登录功能,在综合考量下决定采用cookie实现,大概的流程如下图所: 转载于:https://www.cnblogs.com/bugge ...

最新文章

  1. 0x66.图论 - Tarjan算法与无向图连通性
  2. 关于java中的各种流
  3. wxWidgets随笔(13)-wxBoxSizer类Basic Box Sizer(2)
  4. 朱林北京大学计算机学院,北大、清华状元谈英语学习经验-20210411145045.docx-原创力文档...
  5. 基于CSMA -CA协议的无线星型网络的应用案例介绍
  6. 【JSTL】<c:if test=“”>没有else的解决方法
  7. 跟我一起学docker(九)--持续系统集成了解下git
  8. php和vue实现智商在线测试题
  9. ubuntu系统firefox浏览器无法播放音视频
  10. 不在同一局域网?组建家庭局域网的方案和踩坑
  11. 想成为游戏原画师需要哪些系统的学习?
  12. 马云说过的计算机名言,马云说过最洗脑10名言 马云经典语录大全
  13. 重磅公开!集14位名师教案的《最全高中数学解题思想方法汇编》
  14. linux命令vi编辑文件注释掉某一行,请问linux的vi命令进入文本编辑后怎么去删除一行?...
  15. Scrape Center爬虫平台之spa8案例
  16. 如何提升测试人员在公司的地位
  17. 唯一能够胜过对手的,只有你的学习能力
  18. 实验八 页面置换模拟程序设计
  19. linux怎么添加拼音输入法,ubuntu如何安装中文输入法
  20. 搜索引擎搜索特定网站的方法 :site

热门文章

  1. Spring Cloud Config 配置的加密解密
  2. 如何在Mac电脑上取消Apple Music订阅?
  3. 深度共建产业学院项目合作协议-某真实案例
  4. iOS16.1开发者预览版Beta3发布:优化壁纸功能
  5. b01lers CTF web 复现
  6. 透视色轮(超赞的设计色彩研究)
  7. android 电脑屏幕扩展,Windows 有一个自带功能,帮你轻松实现大屏、小屏无线扩展...
  8. word如何弄成两竖列_在Word中怎么将文字改成竖排显示?
  9. 笔记本扬声器无声音,必须断电重启问题
  10. java文件服务器出售,java文件服务器