shiro,redis,cache实现共享session代码中几个注意的地方改进
即shiro把session部分交给我redis管理:注意:
token.setRememberMe(true);// 设计记住用户,这样才能机器转义后cookie-->session的反向生成
shiro集成cas就是把认证这块交给了cas
1, setExtNo 就这个特殊还没跳转完,还没写好cookie就用了(判断没有就用shiro自己的)
2,在登录的时候没有当前的cookie就用来存 websession -->LoginFilter
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
Subject currentUser = SecurityUtils.getSubject(); // 获取当前的Subject
// 验证是否登录成功
String resultPageURL = "/flex/rbac/preLogin.action";// InternalResourceViewResolver.FORWARD_URL_PREFIX
// + "/";
String username = request.getParameter("j_username");
String password = request.getParameter("j_password");
RequestDispatcher rd = null;
HttpServletRequest request1 =(HttpServletRequest) ((WebSubject)SecurityUtils.getSubject()).getServletRequest(); //ServletActionContext.getRequest();
Cookie[] cookies = request1.getCookies();
String username1=getCookieValue(cookies, "username");
//此时还没有就用shrio自己的,后续生成cookie,username1此时还是上一次的就用shiro自己的
if(username!=null&&((username1==null||username1=="")||!username.equals(username1))){
username1=username;
}
WebSession webSession= WebSessionManager.getInstance().getSession(username1);
if(webSession==null){
webSession=WebSessionManager.getInstance().createSession(username1);
}
String uk="Subject"+username1;
Subject currentUserrds=(Subject)webSession.getAttribute(uk);
if(currentUserrds!=null&¤tUserrds.getSession()!=null){
currentUser=currentUserrds;
}
// 验证是否登录成功
if (currentUser.isAuthenticated()) {
System.out.println("用户[" + currentUser.getSession().getAttribute("j_username") + "]登录认证通过");
authenticationFilter.setLoginSession(request, response);
rd = request.getRequestDispatcher("/flex/rbac/getLoginIndex.action");
// response.setBufferSize(1024000000);
rd.forward(request, response);
return;
// chain.doFilter(request, response);
} else {
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
HttpServletResponse res = (HttpServletResponse)response;
request.setAttribute("msg", "您的账号存在信息不全的问题,请联系管理员完善信息!");
System.out.println("登录过滤器@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
rd = request.getRequestDispatcher("/flex/rbac/preLogin.action");
rd.forward(request, response);
return;
}
// password = MD5.encryptMD5(Base64.encode(password));
/* password = MD5.encryptMD5(Base64.encode("111111")); */
UsernamePasswordToken token = new UsernamePasswordToken(username, password); // 为了验证登录用户而封装的token
token.setRememberMe(true);// 设计记住用户
try {
// 在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查
// 每个Realm都能在必要时对提交的AuthenticationTokens作出反应
// 所以这一步在调用login(token)方法时,它会走到AuthenticationRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法
currentUser.login(token);
resultPageURL = "/flex/rbac/preLogin.action";
} catch (UnknownAccountException uae) {
System.out.println("对用户[" + username + "]进行登录验证..验证未通过,未知账户");
request.setAttribute("msg", "未知账户");//message_login
} catch (IncorrectCredentialsException ice) {
System.out.println("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证");
request.setAttribute("msg", "密码不正确");
} catch (LockedAccountException lae) {
System.out.println("对用户[" + username + "]进行登录验证..验证未通过,账户已锁定");
request.setAttribute("msg", "账户已锁定");
} catch (ExcessiveAttemptsException eae) {
System.out.println("对用户[" + username + "]进行登录验证..验证未通过,错误次数过多");
request.setAttribute("msg", "用户名或密码错误次数过多");
} catch (AuthenticationException ae) {
// 通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景
System.out.println("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下");
ae.printStackTrace();
request.setAttribute("msg", "用户名或密码不正确");
}
if (currentUser.isAuthenticated()) {
System.out.println("用户[" + username + "]登录认证通过");
authenticationFilter.setLoginSession(request, response);
rd = request.getRequestDispatcher("/flex/rbac/getLoginIndex.action");
rd.forward(request, response);
return;
// chain.doFilter(request, response);
} else {
token.clear();
}
}
// chain.doFilter(request, response);
// HttpServletResponse res = (HttpServletResponse)response;
// request.setAttribute("msg", "您的账号存在信息不全的问题,请联系管理员完善信息!");
// System.out.println("登录过滤器@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
rd = request.getRequestDispatcher(resultPageURL);
rd.forward(request, response);
return;
}
之前保存的是其他账户(紧上次)
String username1=getCookieValue(cookies, "username");同一个浏览器切换账户时,用的是上次成功的(只有登录完成之后有response才cookie记录)
没设置cooking共享成功但是登录成功(浏览器记住了缓存的缘故),后面用共享session的时候就出错(所以要清缓存)
Subject currentUser = SecurityUtils.getSubject(); // 获取当前的Subject 这个直接根据cookie获取,对比session 判断状态// 验证是否登录成功,和输入框五个
if (currentUser.isAuthenticated())
j_acegi_security_check这就就是优先走isAuthenticated校验
3,
在认证通过之后才setcookies--》走完loginfilter调用MyAuthenticationFilter这里的savecooike方法
MyAuthenticationFilter
ShiroDbRealm(这时就用了),没设置cooking共享成功但是登录成功(浏览器记住了缓存的缘故),后面用共享session的时候就出错(所以要清缓存)
loginfilt还是拿到了以前的用户(没有正常退出(浏览器记住了缓存的缘故))
就不走ShiroDbRealm就无法记录共享的session信息
1ShiroDbRealm
2MyAuthenticationFilter
跳转以后才有cookie
private void userRolesInit(){
//Subject currentUser = SecurityUtils.getSubject();
//UserDetailsBean shiroUser = (UserDetailsBean) currentUser.getPrincipal();//userDetailsSessionService.getUserId();
HttpServletRequest request1 =(HttpServletRequest) ((WebSubject)SecurityUtils.getSubject()).getServletRequest();
Cookie[] cookies = request1.getCookies();
String username=getCookieValue(cookies, "username");
WebSession webSession= WebSessionManager.getInstance().getSession(username);
4,
ie浏览器的时候,cookie会比chrome写的慢,这就出现chrome可以拿到,ie还是拿不到,要比较久,这时需处理拿不到的时候用shiro自带的
Cookie[] cookies = request1.getCookies();
String username=getCookieValue(cookies, "username");
Subject currentUser = SecurityUtils.getSubject();
UserDetailsBean shiroUser = (currentUser==null?new UserDetailsBean():(UserDetailsBean)currentUser.getPrincipal());
logger.info("username=========="+username);
logger.info("shiroUser=========="+shiroUser);
logger.info("shiroUser.getUserId()=========="+shiroUser.getUserId());
if(username!=null&&(shiroUser==null||shiroUser.getUserId()==null||username.equals(shiroUser.getUserId()))){
WebSession webSession= WebSessionManager.getInstance().getSession(username);
shiroUser = (UserDetailsBean) webSession.getAttribute(username);
}
================================
上述用到的自己利用cookie不需要
其实shiro实现了session的共享之后切换
Subject currentUser = SecurityUtils.getSubject();
UserDetailsBean shiroUser = (UserDetailsBean)currentUser.getPrincipal();
这个方法的值也是利用cookie中的sessionid从cookie中获取,然后直接从共享缓存获取
不需要如下代码自己把客户信息缓存到一个session(自定义的和shiro无关的)中。这也就不需要自己向cookie写入键值,然后拿出用其setvalue,getvalue
public String getUserId()
{
try {
InetAddress address = InetAddress.getLocalHost();//获取的是本地的IP地址 //PC-20140317PXKX/192.168.0.121
String hostAddress = address.getHostAddress();
logger.info("============ip地址==================="+hostAddress);
System.out.println(hostAddress);
}catch (Exception e){
}
HttpServletRequest request1 =(HttpServletRequest) ((WebSubject)SecurityUtils.getSubject()).getServletRequest();
Cookie[] cookies = request1.getCookies();
String username=getCookieValue(cookies, "username");
Subject currentUser = SecurityUtils.getSubject();
UserDetailsBean shiroUser = (currentUser==null?new UserDetailsBean():(UserDetailsBean)currentUser.getPrincipal());
// logger.info("username=========="+username);
// logger.info("shiroUser=========="+shiroUser);
// logger.info("shiroUser.getUserId()==========");
// if(username!=null&&(shiroUser==null||shiroUser.getUserId()==null||username.equals(shiroUser.getUserId()))){
// WebSession webSession= WebSessionManager.getInstance().getSession(username);
//
// if(webSession!=null){
// UserDetailsBean shiroUser1 = (UserDetailsBean) webSession.getAttribute(username);
// if(shiroUser1!=null){
// logger.info("shiroUser1=========="+shiroUser1);
// shiroUser =shiroUser1;
// }else{
// shiroUser =(UserDetailsBean)currentUser.getPrincipal();
// }
//
// logger.info("shiroUser2=========="+shiroUser);
// }else{
// shiroUser =(UserDetailsBean)currentUser.getPrincipal();
// }
//
//
// }
logger.info("shiroUser3=========="+shiroUser);
String ccidExtno= request1.getParameter("j_extno");
shiroUser.setExtNo(ccidExtno==null?"":ccidExtno);
// Subject currentUser = SecurityUtils.getSubject();
// UserDetailsBean shiroUser = (UserDetailsBean) currentUser.getPrincipal();//userDetailsSessionService.getUserId();
//UserDetailsBean agentUser = (UserDetailsBean)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return shiroUser.getUserId();
}
注意
MyAuthenticationFilter中onLoginSuccess中的session.stop();需要注掉,否则用框架的登陆走了onLoginSuccess然后又清了session会报错
相关推荐
"Spring Boot + Shiro + Redis 实现 Session 共享方案二" 1. 概述 本文档旨在介绍如何使用 Spring Boot、Shiro 和 Redis 实现分布式 session 共享,以解决 Web 应用程序的登录 session 统一问题。 2. 相关依赖 ...
`shiro-redisson` 模块就是为了解决这个问题,将 Shiro 的缓存(Cache)和会话(Session)管理功能与 Redis 结合,实现了基于 Redis 的分布式解决方案。 1. **Redisson 库的介绍** Redisson 是一个全面的 Redis ...
总结来说,这个例子展示了如何在SpringBoot项目中利用Shiro进行安全控制,借助Redis实现session的分布式共享,以及利用Redis作为缓存提高系统性能。通过这样的集成,我们可以构建出一个既安全又高效的分布式Web应用...
Spring Boot 整合 Redis 实现 Shiro 的分布式 Session 共享 Shiro 是一个优秀的 Java 安全框架,提供了强大的身份验证、授权和会话管理功能。然而,在分布式架构中,Shiro 的会话管理机制需要进行特殊处理,以便...
在分布式系统中,尤其是在使用Redis作为缓存或session存储时,Shiro的原生支持可能无法直接与Redis集群配合工作。这里提到的"shiro-redis-cluster"项目,显然是针对这个问题进行的一个定制化改造,它使得Shiro能够...
本人提供这个Shiro + SpringMvc + Mybatis + Redis 的Demo 本着学习的态度,如果有欠缺和不足的地方,给予指正,并且多多包涵。 “去其糟粕取其精华”。如果觉得写的好的地方就给个赞,写的不好的地方,也请多多包涵...
标题 "springboot整合redis+shiro" 描述的是一个基于Spring Boot的应用程序,该应用程序集成了Redis和Apache Shiro框架,以实现权限管理和用户认证。这个项目还包含了SQL文件,可以方便地部署和运行,但前提是你需要...
- 在Shiro的配置中,启用Redis和Ecache缓存,存储Session和权限信息。 - 编写Controller和Service层代码,处理业务逻辑,利用Shiro进行权限控制。 这样的整合可以帮助开发者构建出高效、安全的Web应用,既能实现...
2、环境搭建 ①配置java7、gradle2.2.1、redis3.0.4环境; ②在java代码中配置org.demo.shiro.rediscache.RedisClient.redisServerIp
- **Session Management**:Shiro默认使用内存中的session管理,但也可以配置为使用Redis、Memcached等分布式session存储。 **4. 使用Shiro注意事项** - Shiro并不处理Spring的AOP事务,因此需要单独配置事务管理。...
5. 集成 Session 管理:Shiro 可以与 Spring Session 集成,实现分布式会话管理,尤其在微服务环境中。 四、Shiro 缓存处理 为了提高性能,Shiro 支持缓存机制,可以在认证和授权过程中减少对数据库的访问。常见的...
at org.crazycake.shiro.RedisCache.values(RedisCache.java:249) at org.apache.shiro.session.mgt.eis.CachingSessionDAO.getActiveSessions(CachingSessionDAO.java:345) at ...
Spring-boot-shiro-spring-session-redis-example项目启动后输入:该项目中, 增加了对url的拦截,用admin/123456,拥有index权限reports未任何权限, jdonee/123456尚未分配任何权限.参考shiro Cache交于Redis进行管理...
Apache Shiro是一个强大的Java安全框架,它为应用程序提供了身份验证(Authentication)、授权(Authorization)以及会话管理(Session Management)等功能。在这个“shiro缓存jar包”中,包含了两个核心组件:`...
在这个 Shiro1.2.2 的源码包中,我们可以探索以下几个关键知识点: 1. **身份认证(Authentication)**:Shiro 提供了认证流程的核心组件,如 Subject、Realms 和 Authenticator。Subject 是 Shiro 的核心接口,...
这个Demo体现shiro的地方主要在两个类以及shiro.xml的配置文件 CustomRealm : 处理了登录验证以及授权.. ShiroAction : 用来传递登录时的用户数据..转换为token传递给realm...之后根据结果做相应的逻辑处理.. shiro....
Shiro支持多种缓存实现,包括本地缓存(如Guava Cache)和分布式缓存(如Redis或Memcached)。 7. **插件体系**: Shiro 具有良好的扩展性,其设计为模块化,开发者可以自定义 Realm 实现特定的数据源接入,或者...
Apache Shiro 是一个强大且易用的 ...通过这个“Shiro应用实例2”,你可以学习到如何在实际的 Web 应用环境中搭建和配置 Shiro,实现用户登录和权限控制。理解并掌握这些知识点将有助于你在开发中构建安全的应用系统。
Apache Shiro 是一个强大且易用的Java安全框架,提供了认证、授权、加密和会话管理功能,可以非常轻松地开发出足够安全的应用。...在学习过程中,务必仔细研究每个配置项和代码段,以便深入理解Shiro的强大功能。