開局扯淡篇:現在互聯網數據越來越大,所以對平臺數據吞吐量越來越高,簡單的框架已經無法滿足系統需要,那麼我們需要用到 分佈式 ,以及緩存。這裏主要總結一下分佈式情況下,通過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即可。
附原理圖:
.......