spring+shiro+redis做单点登录,支持分布式部署

#背景: 由于公司前端引进新的技术react,改变了传统的jsp模式,逐渐走上前后端分离的,并且随着小程序,手机端业务的发展,越来越多的项目在开始往上面迁移,这就导致了权限问题。于是也就开启了sso项目,一个人挖坑一个人填,终于是上线了。 #技术选择 没人指引,没人会,导致了我现在百度里面搜索了sso单点登录,当时发现的是有个鉴权验证的,需要第三方服务,cas实现,搞了一天,门都没摸到,淘汰。后来在网上看到有人用shiro来做sso系统,然后开启了shiro的了解之路。 #前言 我介绍更多的是我机遇shiro做的sso项目,对于shiro是啥,网上很多都有介绍,源码我没看,只知道他大概的实现原理,所以本人是小白一名,深入理解不了,见谅。 #sso系统设想 #####登录 当用户登录的时候,登录验证后,把userInfo信息和一个token对应(UUID生成),放入redis中token为key,userInfo为value,并且把token返回给前端,要求前端每次访问数据必须请求头中放token #####鉴权 提供一个HTTP接口,让各个系统都放入到filter里面,每次数据接口请求,需要传递我token以及当前数据请求路径,sso判断是否有权限请求该接口, #需求 sso需要验证登录,需要验证数据请求权限,需要支持分布式部署 #实现 #####登录

  1. 自定义Realm
<bean id="upmsRealm" class="com.xxx.controller.shiro.UpmsRealm">
        <property name="credentialsMatcher" ref="credentialsMatcher"/>
    </bean>
	当调用 SecurityUtils.getSubject().login(ssoUserNameToken)的时候,会调用重写的方法

登录验证代码 #####鉴权

  1. 自定义PermissionResolver
<!-- 自定义Realm -->
    <bean id="upmsRealm" class="com.ruhnn.controller.shiro.UpmsRealm">
        <property name="credentialsMatcher" ref="credentialsMatcher"/>
        <property name="PermissionResolver" ref="urlPermissionResolver"/>
    </bean>
	
	/**
     * 授权
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
       //该处为伪代码
	   UserInfo userInfo = (UserInfo) SecurityUtils.getSubject().getPrincipal();
        byte[] value = redisClient.get(userInfo.getToken());
        if (value != null) {
            userInfo = SerializeUtil.deserialize(value, UserInfo.class);
        }
        String key = SsoConstants.REDIS_ROLE_KEY + userInfo.getToken() + "-" + userInfo.getWebId();
        Set<String> allPermissions = new HashSet<>();
        byte[] bytes = redisClient.get(key);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(allPermissions);
        return info;
    }

#####分布式部署 必须重写shiro的sessionDAO的管理,我这个是在github上面,有个大哥写的案例,现在找不到了,很感谢大哥给我的启发

<!-- session管理器 -->
    <bean id="sessionManager" class="com.ruhnn.controller.shiro.SsoSessionManager">
        <!-- 设置全局会话超时时间,默认30分钟(1800000) -->
        <property name="globalSessionTimeout" value="86400000"/>
        <!-- 是否在会话过期后会调用SessionDAO的delete方法删除会话 默认true -->
        <property name="deleteInvalidSessions" value="true"/>
        <!-- 会话验证器调度时间 -->
        <property name="sessionValidationInterval" value="1800000"/>
        <!-- session存储的实现 -->
        <property name="sessionDAO" ref="redisCacheSessionDAO"/>
        <property name="sessionIdCookie.name" value="SSO-SESSIONID"/>
    </bean>
    <!--</bean>-->
    <!-- 会话Session ID生成器 -->
    <bean id="sessionIdGenerator" class="com.ruhnn.controller.shiro.JavaUuidSessionIdGenerator"/>
    <bean id="redisCacheSessionDAO" class="com.ruhnn.controller.shiro.RedisCacheSessionDAO">
        <property name="sessionIdGenerator" ref="sessionIdGenerator"/>
    </bean>

重写类

public class RedisCacheSessionDAO extends AbstractSessionDAO {
	//该处需要重写抽象方法
}

#拦截请求 运用shiro的请求拦截,自定义了一些拦截方法

   <!-- Shiro过滤器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- Shiro的核心安全接口,这个属性是必须的 -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 身份认证失败,则跳转到登录页面的配置 -->
        <property name="loginUrl" value="/index"/>
        <!-- 权限认证失败,则跳转到指定页面 -->
        <property name="unauthorizedUrl" value="/index"/>
        <!--登陆成功-->
        <property name="successUrl" value="/index"/>
        <property name="filters">
            <util:map>
                <entry key="token" value-ref="tokenUserFilter"/>
                <entry key="validate" value-ref="validateUserFilter"/>
                <entry key="expire" value-ref="expireTokenUserFilter"/>
            </util:map>
        </property>
        <!-- Shiro连接约束配置,即过滤链的定义 -->
        <property name="filterChainDefinitions">
            <value>
                /login/** = anon
                /logout/** = logout
                /static/**= anon
                /** = token,validate,expire
            </value>
        </property>
    </bean>

token:验证只能请求token的鉴权路径,其他路径一律拦截返回错误 validate:验证是否有token,token是否有效 expire:延长用户token过期时间 #结束语 以上是我花费1个月研究出来的sso系统,没人做技术指导,有的只是需求,有的只是对技术的执着,我不知道我这种实现方式有什么不妥,目前系统已经上线允许,也许是没人搞我们系统,也许是走了狗屎运,目前运行一切正常。记录一下 自己这次的成就,感觉又要逆天了 哈哈哈哈

转载于:https://my.oschina.net/u/1782542/blog/1925940

Spring Boot是一个用于快速开发Java应用程序的开源框架,Shiro是一个强大且易于使用的Java安全框架,Redis是一个开源的内存数据库。结合使用这些技术可以实现单点登录功能。 在Spring Boot中使用Shiro来处理认证和授权,可以通过配置Shiro的Realm来实现用户的登录认证和权限控制。将用户的信息存储在Redis中,利用Redis的持久化特性来实现用户登录状态的共享和存储。 首先,在Spring Boot项目的配置文件中配置Redis的连接信息,以便连接到Redis数据库。 然后,创建一个自定义的Shiro的Realm,在其中重写认证和授权的方法。在认证方法中,将用户的登录信息存储到Redis中,以便其他服务可以进行验证。在授权方法中,根据用户的角色和权限进行相应的授权操作。 接着,在Spring Boot项目的配置类中配置Shiro的相关设置,包括Realm、Session管理器、Cookie管理器等。 最后,可以在Controller层中使用Shiro的注解来标记需要进行认证和授权的接口,以确保只有登录后且具备相应权限的用户才能访问这些接口。 总的来说,通过使用Spring Boot、ShiroRedis的组合,可以实现单点登录的功能。用户在登录后,将登录信息存储到Redis中,其他服务可以通过验证Redis中的数据来判断用户的登录状态。同时,Shiro提供了强大的认证和授权功能,可以确保只有具备相应权限的用户才能访问受保护的接口。这些功能的具体实现可以通过深入研究Spring Boot、ShiroRedis的源码来了解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值