今天突然想到一個問題關於前后不分shiro的WEB項目sessionid安全問題.
前后分離可以使用token作為用戶唯一標志憑證,這個token可以自定義生成規則,
那么前后不分的shiro項目返回的是一串32位的字符串,
我們這里假設攻擊方客戶端足夠多,服務端用戶足夠多,
那么在一定時間,攻擊方無限訪問服務端。是否會命中正確的sessionid。
這里,就想着自定義session生成規則。
下面說一下思路。
Springboot整合Shiro的案例以及Shiro架構網上很多。這里就不說了。
1.DefaultWebSecurityManager
/**
* 注入 securityManager
*/
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(HashedCredentialsMatcher hashedCredentialsMatcher,SessionManager defaultWebSessionManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 關聯realm.
securityManager.setRealm(userRealm(hashedCredentialsMatcher));
securityManager.setSessionManager(defaultWebSessionManager);
return securityManager;
}
此段代碼是必須的,我們這里需要重新自定義SessionMannager里面的一些實現。因為session是SessionMannager生成的
2.觀察setSessionManager方法
@Override
public void setSessionManager(SessionManager sessionManager) {
this.sessionMode = null;
if (sessionManager != null && !(sessionManager instanceof WebSessionManager)) {
if (log.isWarnEnabled()) {
String msg = "The " + getClass().getName() + " implementation expects SessionManager instances " +
"that implement the " + WebSessionManager.class.getName() + " interface. The " +
"configured instance is of type [" + sessionManager.getClass().getName() + "] which does not " +
"implement this interface.. This may cause unexpected behavior.";
log.warn(msg);
}
}
setInternalSessionManager(sessionManager);
}
此處傳入的對象需要是WebSessionManager實例
3.觀察WebSessionManager繼承實現關系,發現DefaultWebSessionManager的父類DefaultSessionManager 有個protected SessionDAO sessionDAO;屬性
4.觀察SessionDAO繼承實現關系抽象類有個SessionIdGenerator接口,這個就是我們需要自己定義的sessionid生成策略了。
5.自定義生成策略
public class SessionIdMine implements SessionIdGenerator{
@Override
public Serializable generateId(Session session) {
return UUID.randomUUID().toString();
}
}
6.將此策略給Spring容器管理
@Bean(name="sessionDAO")
public EnterpriseCacheSessionDAO sessionDAO() {
EnterpriseCacheSessionDAO abstractSessionDAO=new EnterpriseCacheSessionDAO();
abstractSessionDAO.setSessionIdGenerator(new SessionIdMine());
return abstractSessionDAO;
}
EnterpriseCacheSessionDAO為SessionDAO的子類這里需要返回子類作為下一步參數傳遞
7.思考如何將自定義策略實現到shiro,前面說到DefaultWebSessionManager為WebSessionManager最底層實現類,DefaultSessionManager子類,
將DefaultWebSessionManager給Spring管理
@Bean(name="defaultWebSessionManager")
public DefaultWebSessionManager defaultWebSessionManager(EnterpriseCacheSessionDAO sessionDAO) {
DefaultWebSessionManager abstractSessionDAO=new DefaultWebSessionManager();
abstractSessionDAO.setSessionDAO(sessionDAO);
return abstractSessionDAO;
}
8.至此自定義策略完成,網上觀察了一些方法,版本不同實現不同,大體思路就是追源碼,看實現
9.效果

10.補充一下Shirodemo測試地址
https://github.com/Rhine404/shirodemo.git
忘記是哪個寫的了。
