`
y806839048
  • 浏览: 1107440 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

shiro,redis,cache实现共享session代码中几个注意的地方改进

阅读更多

 

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&&currentUserrds.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会报错

分享到:
评论

相关推荐

    springboot +shiro+redis实现session共享(方案二)1

    "Spring Boot + Shiro + Redis 实现 Session 共享方案二" 1. 概述 本文档旨在介绍如何使用 Spring Boot、Shiro 和 Redis 实现分布式 session 共享,以解决 Web 应用程序的登录 session 统一问题。 2. 相关依赖 ...

    shiro-redisson基于Redis的ShiroCache和Session实现

    `shiro-redisson` 模块就是为了解决这个问题,将 Shiro 的缓存(Cache)和会话(Session)管理功能与 Redis 结合,实现了基于 Redis 的分布式解决方案。 1. **Redisson 库的介绍** Redisson 是一个全面的 Redis ...

    springboot shiro redis缓存和session共享例子

    总结来说,这个例子展示了如何在SpringBoot项目中利用Shiro进行安全控制,借助Redis实现session的分布式共享,以及利用Redis作为缓存提高系统性能。通过这样的集成,我们可以构建出一个既安全又高效的分布式Web应用...

    spring boot整合redis实现shiro的分布式session共享的方法

    Spring Boot 整合 Redis 实现 Shiro 的分布式 Session 共享 Shiro 是一个优秀的 Java 安全框架,提供了强大的身份验证、授权和会话管理功能。然而,在分布式架构中,Shiro 的会话管理机制需要进行特殊处理,以便...

    shiro连接redis集群 根据org.crazycake.shiro包改造源码

    在分布式系统中,尤其是在使用Redis作为缓存或session存储时,Shiro的原生支持可能无法直接与Redis集群配合工作。这里提到的"shiro-redis-cluster"项目,显然是针对这个问题进行的一个定制化改造,它使得Shiro能够...

    SpringMVC-Mybatis-Shiro-redis-master 权限集成缓存中实例

    本人提供这个Shiro + SpringMvc + Mybatis + Redis 的Demo 本着学习的态度,如果有欠缺和不足的地方,给予指正,并且多多包涵。 “去其糟粕取其精华”。如果觉得写的好的地方就给个赞,写的不好的地方,也请多多包涵...

    springboot整合redis+shiro

    标题 "springboot整合redis+shiro" 描述的是一个基于Spring Boot的应用程序,该应用程序集成了Redis和Apache Shiro框架,以实现权限管理和用户认证。这个项目还包含了SQL文件,可以方便地部署和运行,但前提是你需要...

    ssm+shiro+redis+ecache整合认证权限.zip

    - 在Shiro的配置中,启用Redis和Ecache缓存,存储Session和权限信息。 - 编写Controller和Service层代码,处理业务逻辑,利用Shiro进行权限控制。 这样的整合可以帮助开发者构建出高效、安全的Web应用,既能实现...

    shiro会话共享实战

    2、环境搭建 ①配置java7、gradle2.2.1、redis3.0.4环境; ②在java代码中配置org.demo.shiro.rediscache.RedisClient.redisServerIp

    shiro所需的全部jar包

    - **Session Management**:Shiro默认使用内存中的session管理,但也可以配置为使用Redis、Memcached等分布式session存储。 **4. 使用Shiro注意事项** - Shiro并不处理Spring的AOP事务,因此需要单独配置事务管理。...

    spring boot+shiro 权限认证管理案例

    5. 集成 Session 管理:Shiro 可以与 Spring Session 集成,实现分布式会话管理,尤其在微服务环境中。 四、Shiro 缓存处理 为了提高性能,Shiro 支持缓存机制,可以在认证和授权过程中减少对数据库的访问。常见的...

    jedis-3.3.0.jar

    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

    Spring-boot-shiro-spring-session-redis-example项目启动后输入:该项目中, 增加了对url的拦截,用admin/123456,拥有index权限reports未任何权限, jdonee/123456尚未分配任何权限.参考shiro Cache交于Redis进行管理...

    shiro缓存jar包

    Apache Shiro是一个强大的Java安全框架,它为应用程序提供了身份验证(Authentication)、授权(Authorization)以及会话管理(Session Management)等功能。在这个“shiro缓存jar包”中,包含了两个核心组件:`...

    Shiro1.2.2_源码(压缩包)

    在这个 Shiro1.2.2 的源码包中,我们可以探索以下几个关键知识点: 1. **身份认证(Authentication)**:Shiro 提供了认证流程的核心组件,如 Subject、Realms 和 Authenticator。Subject 是 Shiro 的核心接口,...

    SpringShiro分布式缓存版

    这个Demo体现shiro的地方主要在两个类以及shiro.xml的配置文件 CustomRealm : 处理了登录验证以及授权.. ShiroAction : 用来传递登录时的用户数据..转换为token传递给realm...之后根据结果做相应的逻辑处理.. shiro....

    shiro源文件

    Shiro支持多种缓存实现,包括本地缓存(如Guava Cache)和分布式缓存(如Redis或Memcached)。 7. **插件体系**: Shiro 具有良好的扩展性,其设计为模块化,开发者可以自定义 Realm 实现特定的数据源接入,或者...

    Shiro应用实例2

    Apache Shiro 是一个强大且易用的 ...通过这个“Shiro应用实例2”,你可以学习到如何在实际的 Web 应用环境中搭建和配置 Shiro,实现用户登录和权限控制。理解并掌握这些知识点将有助于你在开发中构建安全的应用系统。

    跟我学Shiro第11章Demo

    Apache Shiro 是一个强大且易用的Java安全框架,提供了认证、授权、加密和会话管理功能,可以非常轻松地开发出足够安全的应用。...在学习过程中,务必仔细研究每个配置项和代码段,以便深入理解Shiro的强大功能。

Global site tag (gtag.js) - Google Analytics