开局扯淡篇:现在互联网数据越来越大,所以对平台数据吞吐量越来越高,简单的框架已经无法满足系统需要,那么我们需要用到 分布式 ,以及缓存。这里主要总结一下分布式情况下,通过jedis解决session共享以及单点登录的问题。
建议:先初步了解下shrio再看此文章
使用的jar:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-cas</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
</dependency>
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>2.4.2.1-RELEASE</version>
</dependency>
这里重点介绍的 org.crazycake ,上面的shrio是我们常用的登录验证框架
看到这里,希望能把org.crazycake的源码down下来,然后对着看。因为org.crazycake中重写了shrio中的操作session的类,也是我们需要用到它的地方。
Shrio中最核心的类:org.apache.shiro.web.mgt.DefaultWebSecurityManager
他拥有3个重要的属性 :realm(权限验证器)、sessionManager(session管理器)、cacheManager(缓存管理器)
这里需要区分一下:
sessionManager:字面意思,管理session的(这里指shrio的session,不是HttpSession喔)
cacheManager:认证和授权管理器
我们这里主要重新注入这两个属性。
呐,现在看下一下shrio的类结构图
Org.crazycake,帮我们实现了 以上所有属性,
sessionDAO:
org.crazycake.shiro.RedisSessionDAO 第25行:private String keyPrefix = "shiro_redis_session:";
可以看到我们存到redis缓存中的key前缀是"shiro_redis_session:"开头的(也可以注入新的名称)
sessionIdCookie:cookie机制存储name属性指定cookieId
redisManager:操作缓存的类
辣么,以下配置正确的实现了上图所有属性:
<!-- shiro securityManager -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- Single realm app. If you have multiple realms, use the 'realms' property instead. -->
<property name="realm" ref="systemAuthorizingRealm" />
<!-- sessionManager -->
<property name="sessionManager" ref="sessionManager" />
<!-- cacheManager -->
<property name="cacheManager" ref="cacheManager" />
<!-- By default the servlet container sessions will be used. Uncomment this line
to use shiro's native sessions (see the JavaDoc for more): -->
<!-- <property name="sessionMode" value="native"/> -->
</bean>
<!-- shiro redisManager -->
<bean id="redisManager" class="org.crazycake.shiro.RedisManager">
<property name="host" value="${redisManager.host}"/>
<property name="port" value="${redisManager.port}"/>
<property name="expire" value="${redisManager.timeout}"/>
<!-- optional properties:
<property name="timeout" value="10000"/>
<property name="password" value="123456"/>
-->
</bean>
<!-- redisSessionDAO -->
<bean id="redisSessionDAO" class="org.crazycake.shiro.RedisSessionDAO">
<property name="redisManager" ref="redisManager" />
<property name="keyPrefix" value="${redisManager.prefix}"></property>
</bean>
<!-- sessionManager -->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="sessionDAO" ref="redisSessionDAO" />
<property name="sessionIdCookie" ref="sharesession" />
</bean>
<!-- cacheManager -->
<bean id="cacheManager" class="org.crazycake.shiro.RedisCacheManager">
<property name="redisManager" ref="redisManager" />
</bean>
<!-- 安全认证过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/index.html" />
<property name="filterChainDefinitions">
<ref bean="shiroFilterChainDefinitions"/>
</property>
</bean>
<!-- sessionIdCookie的实现,用于重写覆盖容器默认的JSESSIONID -->
<bean id="sharesession" class="org.apache.shiro.web.servlet.SimpleCookie">
<!-- cookie的name,对应的默认是JSESSIONID -->
<constructor-arg name="name" value="${redisManager.sessionname}" />
<!-- jsessionId的path为/用于多个系统共享jsessionId -->
<property name="path" value="/" />
<property name="httpOnly" value="false"/>
</bean>
Java代码中,通过SecurityUtils.getSubject().getSession()获取session即可。
附原理图:
.......