在玩 spring boot 集成 shiro ,,,可是 发现 它的 session 和 cookie 把我搞得有点懵了。。。
首先 声明 session 和 cookie 的 区别,,,其实 session 和 cookie 是 一样的东西,
**顺便提一下,,,在web项目里面 shiro 里面 操作的 session ,管理的 session 其实 本质上就是 web http 的 session , 至少换了一个名称而已。。。别被 shiro的 session 和 http 的 session 区分开了,他们就是一样的。具体可以百度 **
1, session 实现
每次请求的时候 都会 产生 一个 cookie ,这个 cookie 会把 session id 放进去,,, 传出去给客户端 和自己的服务器里面 也会把 sessionid 给保存起来,,, 这样的方式 就是 叫做 session ,它的实现方式就是 cookie 的技术。 这个 cookie 在 浏览器 客户端的生命周期就是: 如果不设置 过期时间,则表示这个 Cookie生命周期为 浏览器会话期间 , 只要关闭浏览器,cookie就消失了. 这个生命期为浏览会话期的cookie,就是会话Cookie;
下面 是 给出的 shiro 的 配置的一个 自定义的 session 管理器里面 对 session 的 设置:
/**
* session管理器
*/
@Bean
public DefaultWebSessionManager defaultWebSessionManager(CacheManager cacheShiroManager, GunsProperties gunsProperties) {
// 本质上 shiro 操作的 session 就是 http web session 的
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setCacheManager(cacheShiroManager);
sessionManager.setSessionValidationInterval(gunsProperties.getSessionValidationInterval() * 1000);
sessionManager.setGlobalSessionTimeout(gunsProperties.getSessionInvalidateTime() * 1000);
sessionManager.setDeleteInvalidSessions(true);
sessionManager.setSessionValidationSchedulerEnabled(true);
Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
cookie.setName("shiroCookie"); // 修改默认的 session 的 名称 , 这里没有 设置 session的 cookie 生命周期,
//默认就是 浏览器关闭时候或者服务器设置的 session 的时间
cookie.setHttpOnly(true);
sessionManager.setSessionIdCookie(cookie);
return sessionManager;
}
这样 使用 shiro 拦截了 访问的地址之后,,你就会发现 ,在 浏览器的 对应的 cookie 列表里面,,看到 对应的 访问域名 下的,就 有一个 cookie 了, 它的名称就是 shiroCookie , 它就是 存放的就是 sessionid 内容。 默认如果我们 不设置 的话,存放 web的 sessionid 的 cookie 就叫 做 JSESSIONID 的。 这里并没有设置 它的生命周期,默认就是 浏览器 打开的时间,浏览器一关闭,在客户端就看不到了。
2 , cookie
而我们 开发中 使用到的其他的 cookie ,就是将 内容存放在 客户端,然后 在 客户端指定这个 cookie的 生命周期,,,当然了 这个 cookie 的内容我们一般是加密了的。 这种 cookie 在服务器里面 是不会 存的。 下面是 shrio 自定义的一个 存放 shrio的 内容的 免登陆的 cookie
/**
* 记住密码Cookie
*/
@Bean
public SimpleCookie rememberMeCookie() {
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
simpleCookie.setHttpOnly(true);
simpleCookie.setMaxAge(7 * 24 * 60 * 60);//7天
return simpleCookie;
}
/**
* rememberMe管理器, cipherKey生成见{@code Base64Test.java}
*/
@Bean
public CookieRememberMeManager rememberMeManager(SimpleCookie rememberMeCookie) {
CookieRememberMeManager manager = new CookieRememberMeManager();
manager.setCipherKey(Base64.decode("Z3VucwAAAAAAAAAAAAAAAA=="));
manager.setCookie(rememberMeCookie);
return manager;
}
主要讲下shiro的rememberMe cookie。在shiro中有一个类实现了rememberMe功能, org.apache.shiro.web.mgt.CookieRememberMeManager 。在登录时,代码也很简单:
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
token.setRememberMe(true);
subject.login(token);
RememberMe这个参数设置为true后,在登陆的时候就会在客户端设置remenberme的相应cookie。下次访问带上这个cookie,访问链接为user链接器的,就不需要进行登录验证,直接进入权限验证。下面是完整的处理过程:
得到principals对象
通过配置的key,使用aes加密
将加密后的值再通过base64解密
当客户端带着这个rememberMe cookie访问时,将会按照下面的过程来寻找已记住的身份信息:
获取rememberMe cookie的值
Base64解码
使用AES解密
使用ObjectInputStream进行反序列化
这样不需要进入身份验证的拦截器,就直接从cookie中获取到了登录信息。
这样就会在客户端 看到一个 cookie 叫做 remenberMe 了 ,浏览器关闭了 也是会存在的,而且 有效时间的是 7 天 。
session很容易失效,用户体验差点;
虽然cookie不安全,但是可以加密 ;
cookie也分为永久 和暂时 存在的;
浏览器 有禁止cookie功能 ,但一般用户都不会设置;
一定要设置失效时间,要不然浏览器关闭就消失了;
要是 说到 安全性,,当然是 session 安全性比较高一点了,
但是 cookie 还是有其他使用的 场景的 。
参考地址:
https://www.zhihu.com/question/19786827
http://www.jianshu.com/p/4972c4d70853
3, 那么 使用 shrio 的cookie 免登陆 到底是 怎么 实现 和 原理的呢 ? 我觉得这个 可以去看 源码了
我觉得 可以 通过 shrio 的 debug 日志可以看出一二 : 下面是我的cookie 免登陆的 debug
INFO o.s.web.servlet.DispatcherServlet - FrameworkServlet 'dispatcherServlet': initialization completed in 131 ms
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] INFO o.s.web.servlet.DispatcherServlet - FrameworkServlet 'dispatcherServlet': initialization completed in 131 ms
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - Servlet 'dispatcherServlet' configured successfully
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - Servlet 'dispatcherServlet' configured successfully
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.a.s.s.m.AbstractValidatingSessionManager - No sessionValidationScheduler set. Attempting to create default instance.
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.a.s.s.m.AbstractValidatingSessionManager - No sessionValidationScheduler set. Attempting to create default instance.
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] INFO o.a.s.s.m.AbstractValidatingSessionManager - Enabling session validation scheduler...
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] INFO o.a.s.s.m.AbstractValidatingSessionManager - Enabling session validation scheduler...
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.a.s.s.mgt.DefaultSessionManager - Unable to resolve session ID from SessionKey [org.apache.shiro.web.session.mgt.WebSessionKey@7a5b1ab0]. Returning null to indicate a session could not be found.
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.a.s.s.mgt.DefaultSessionManager - Unable to resolve session ID from SessionKey [org.apache.shiro.web.session.mgt.WebSessionKey@7a5b1ab0]. Returning null to indicate a session could not be found.
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.a.shiro.web.servlet.SimpleCookie - Found 'rememberMe' cookie value [LygBMpYB855BJwNhZ4QAXubesRMdb/cNjxrhhihTTcv9OwsTJ2OO/6R1QKtla5sU3R9QuxkhGOJYwhjqgIGT/9pc794puGndtLkgPEkBL6ee3eBajBDvrAK8HULXt9r5GWnY1GwLJs1AHJjAsflGZLvhIeFGEiYkXQZo4zPLyLVU5EMCoLMDj8qMBd29Ey0ZtJIEVLepBhrMMhR7Pa2sLMylvmgSE4/RlvGnXLq3lb7fv1eMDZFcHh6gQ/2SEOB1yjTx9ag/+4ARExatszVCZSw5/UaWDoQuSwGxAlz32z3HHWSQuR6CUh35BFO5wXEvJzI1bsIkzpySzsVM7w5n3jtAL2SucKdW1BoHbbOiQAimpPaHh0ZSbsE+WEpFxVBxDWCGoJ82WBUareMhec6wc0B+fQ/PMSwXjCkzKU3hkQPquZiCgyPSS8colg01LNfoJiQlCENUCZwn2ouGtYVUg5M7XnMwpaVfxxyminU5V3YsrVokTqIMQtTXt+RJyJq4SEBhXMZeI2u6ZBS8oa7rYA/3PFx8QfHD1QUXqH9JrMr4p3PPPfRIIfnwmM1l7qKorhd1wH0fP+1gwpqJqcflcJ+lnT6tl2V127mJEM8xQcPmbrryu9y9T+6uEwbNEZ1A9s9ipgWo2ULOupjn/VXCVWOYwDKbFaA81mjbsfK4udSB+7UScfl0Y89uYy+SjgPGhpxU+ISl1sqJ3Whu7I2W4RsuPdIbtjV4nOV2qhrlZH0EBQXxHarviNfI2QvXfe7zRPMU8cXqtDmFiZQEfo+OQXSONZSnbwOmlho3/XRlOG4d7kAiEly2nQ9K+Itx+XBkd5jLTaP0iGcR9b2GB5GyhI6npx8P2oVROxZec2FflDzj/vZr+j3vQZPC08LeKPWVGnhTC3IiD+801LY/X31agrHDPJqtbsOnJHmYPN2Xcc8RMNoWdZp9Sxyl+qJ5QWCaQJvMH5NKZgfVvvI67zQIfK5VGSdFDIQmR2r/Zz5dsgOoNs+iwmMMsE31P8SGZcEURCjZRHGKomnimxC3S9qMQU/MCLSC3U1WHGyVOyKdiS+zGzSdYb6ARTDjMUcGcEmS]
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.a.shiro.web.servlet.SimpleCookie - Found 'rememberMe' cookie value [LygBMpYB855BJwNhZ4QAXubesRMdb/cNjxrhhihTTcv9OwsTJ2OO/6R1QKtla5sU3R9QuxkhGOJYwhjqgIGT/9pc794puGndtLkgPEkBL6ee3eBajBDvrAK8HULXt9r5GWnY1GwLJs1AHJjAsflGZLvhIeFGEiYkXQZo4zPLyLVU5EMCoLMDj8qMBd29Ey0ZtJIEVLepBhrMMhR7Pa2sLMylvmgSE4/RlvGnXLq3lb7fv1eMDZFcHh6gQ/2SEOB1yjTx9ag/+4ARExatszVCZSw5/UaWDoQuSwGxAlz32z3HHWSQuR6CUh35BFO5wXEvJzI1bsIkzpySzsVM7w5n3jtAL2SucKdW1BoHbbOiQAimpPaHh0ZSbsE+WEpFxVBxDWCGoJ82WBUareMhec6wc0B+fQ/PMSwXjCkzKU3hkQPquZiCgyPSS8colg01LNfoJiQlCENUCZwn2ouGtYVUg5M7XnMwpaVfxxyminU5V3YsrVokTqIMQtTXt+RJyJq4SEBhXMZeI2u6ZBS8oa7rYA/3PFx8QfHD1QUXqH9JrMr4p3PPPfRIIfnwmM1l7qKorhd1wH0fP+1gwpqJqcflcJ+lnT6tl2V127mJEM8xQcPmbrryu9y9T+6uEwbNEZ1A9s9ipgWo2ULOupjn/VXCVWOYwDKbFaA81mjbsfK4udSB+7UScfl0Y89uYy+SjgPGhpxU+ISl1sqJ3Whu7I2W4RsuPdIbtjV4nOV2qhrlZH0EBQXxHarviNfI2QvXfe7zRPMU8cXqtDmFiZQEfo+OQXSONZSnbwOmlho3/XRlOG4d7kAiEly2nQ9K+Itx+XBkd5jLTaP0iGcR9b2GB5GyhI6npx8P2oVROxZec2FflDzj/vZr+j3vQZPC08LeKPWVGnhTC3IiD+801LY/X31agrHDPJqtbsOnJHmYPN2Xcc8RMNoWdZp9Sxyl+qJ5QWCaQJvMH5NKZgfVvvI67zQIfK5VGSdFDIQmR2r/Zz5dsgOoNs+iwmMMsE31P8SGZcEURCjZRHGKomnimxC3S9qMQU/MCLSC3U1WHGyVOyKdiS+zGzSdYb6ARTDjMUcGcEmS]
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.a.shiro.mgt.DefaultSecurityManager - Found remembered PrincipalCollection. Adding to the context to be used for subject construction by the SubjectFactory.
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.a.shiro.mgt.DefaultSecurityManager - Found remembered PrincipalCollection. Adding to the context to be used for subject construction by the SubjectFactory.
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.a.s.s.mgt.DefaultSessionManager - Creating new EIS record for new session instance [org.apache.shiro.session.mgt.SimpleSession,id=null]
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.a.s.s.mgt.DefaultSessionManager - Creating new EIS record for new session instance [org.apache.shiro.session.mgt.SimpleSession,id=null]
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.a.shiro.web.servlet.SimpleCookie - Added HttpServletResponse Cookie [shiroCookie=905b3559-9d1e-451f-a151-339444a1c868; Path=/; HttpOnly]
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.a.shiro.web.servlet.SimpleCookie - Added HttpServletResponse Cookie [shiroCookie=905b3559-9d1e-451f-a151-339444a1c868; Path=/; HttpOnly]
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'dispatcherServlet' processing GET request for [/]
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'dispatcherServlet' processing GET request for [/]
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - Last-Modified value for [/] is: -1
[guns] 2017-06-28 13:45:05 [http-nio-80-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - Last-Modified value for [/] is: -1
其实它的步骤是这样的,,, 请求的路径,,,首先配置了不需要权限,,, 然后 通过 request 获取 cookie 的值,如果有值 ,而且 是配置 的 remerberMe 的:
SimpleCookie - Found 'rememberMe' cookie value
拿到 cookie 里面的值, 直接 就 自动 有一个 shrio 工厂了,直接不需要 登陆验证的了,产生了 shrio 用户对象。
Found remembered PrincipalCollection. Adding to the context to be used for subject construction by the SubjectFactory.
看产生了 Principal 对象了,,, 这个 rememberMe cookie 在密码登陆成功时候会自动将 用户信息和密码等其他一起 放入 rememberMe cookie 这个里面的,,,现在 只是 后端获取 这个信息,然后 产生一个 认证对象。
顺便提一下,,接着呢,发现 客户端没有 sessionID ,就自动产生一个 sessionId 给客户端,就是我们说的 session 了: shiroCookie 这个是我的本地程序修改的 session 的名称
Added HttpServletResponse Cookie [shiroCookie=905b3559-9d1e-451f-a151-339444a1c868; Path=/; HttpOnly]