cocosum 2019-11-11 21:48 采纳率: 33.3%
浏览 1300
已结题

Springboot整合Shiro 记住密码(RememberM)之后怎么实现重启浏览器,我的登录信息也不过期?

  1. cookie管理对象
@Bean
    public CookieRememberMeManager cookieRememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        simpleCookie.setMaxAge(259200000);
        cookieRememberMeManager.setCookie(simpleCookie);
        cookieRememberMeManager.setCipherKey(Base64.decode("6Zm+6I2j5Y+R5aS+5ZOlAA=="));
        return cookieRememberMeManager;
    }
  1. 上面可以实现cookie保存,重启浏览器,无需登录;但是我发现,cookie虽在, 如我重启之后,ajax调用getRequest().getSession().getAttribute("userName") 这个时候发现Session已经不存在。会报java.lang.NullPointerException空指针异常。在网上找了博客,有些有人说关闭浏览器cookie都也释放了,但是我上面确实也能实现关闭重启之后无需登录,只要不获取session。在程序里面不获取session不可能的。
  2. 哪位大佬能给点解释?怎么才能实现关闭浏览器session也不过期? 记住密码之后,关闭浏览器,重启电脑再次打开也无需登录?

解决办法:

    /**
     * cookie对象;
     * @return
     */
    @Bean
    public SimpleCookie rememberMeCookie(){
        // 这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        // cookie生效时间30天,单位秒;
        simpleCookie.setMaxAge(2592000);
        // 浏览器中通过document.cookie可以获取cookie属性,设置了HttpOnly=true,在脚本中就不能的到cookie,可以避免cookie被盗用
        simpleCookie.setHttpOnly(true);
        // JSESSIONID的path为/用于多个系统共享JSESSIONID
        simpleCookie.setPath("/");
        return simpleCookie;
    }

    /**
     * cookie管理对象;记住我功能
     * @return
     */
    @Bean
    public CookieRememberMeManager rememberMeManager(){
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        // rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
        cookieRememberMeManager.setCipherKey(Base64.decode("2A2V+RFLUs+eTA3Kpr+dag=="));
        return cookieRememberMeManager;
    }

    /**
     * 自定义过滤器
     * @author : fyk
     * @create : 2019/11/14 16:12
     **/
    @Bean
    public CustomUserFilter customUserFilter() {
        CustomUserFilter customUserFilter = new CustomUserFilter();
        return customUserFilter;
    }
package com.cocosum.blog.core.shiro.filter;

import com.cocosum.blog.commons.utils.SysConstant;
import com.cocosum.blog.system.entity.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Objects;

/**
 * 自定义过滤器
 * @author : fyk
 * @create : 2019/11/14 17:06
 **/
@Slf4j
public class CustomUserFilter extends AccessControlFilter {

    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        Subject subject = getSubject(request, response);
        if (subject == null) {
            return false;
        }
        // 转成HttpSession对象
        HttpSession session = ((HttpServletRequest) request).getSession();
        // 获取当前登录用户(获取用户)
        Object userName = session.getAttribute(SysConstant.UserConstant.USER_NAME);
        // 如果因为session过时或者浏览器关闭,导致保存的登录信息随着session的关闭而清空了
        if (Objects.isNull(userName)) {
            // 获取主体信息, session被清空之后,主体信息不会被清除掉
            UserInfo userInfo = (UserInfo) subject.getPrincipal();
            if (Objects.nonNull(userInfo)) {
                session.setAttribute(SysConstant.UserConstant.USER_NAME, userInfo.getUserName());
            } else {
                // 否则session与主体信息都为空,那就说明没有登录。则需要重新登录
            }

        }
        return true;
    }

    @Override
    protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {
        return true;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        return true;
    }
}

  • 写回答

2条回答 默认 最新

  • Amo_lt 2019-11-12 14:00
    关注

    1.我设置rememberme无效,你可以自己将用户名和密码存到cookie里。
    2.你既然有登录,那应该有个过滤器或拦截器,进行session判断。
    3.在这个过滤器或拦截器的session判断中,若session为空,则从cookie里取到用户名和密码(req.getCookies();),

    Cookie[] cookies=req.getCookies();
                if(cookies!=null){//获取客户端Cookie
                    for(Cookie c:cookies){
                        if(c.getName().equals("userName")){
                            userName=c.getValue();
                        }
                        if(c.getName().equals("password")){
                            passWord=c.getValue();
                        }
                    }
                }
    

    再使用subject.login(token);(你原来的登录方法)进行登录。

    UsernamePasswordToken token = new UsernamePasswordToken(userName, passWord.toUpperCase().toCharArray());
    
                        subject.login(token);
    

    然后刷新cookie的到期时间以及session的值。

    //登录成功刷新客户端Cookie
                        Cookie userNameCookie = new Cookie("userName", userName);
                        Cookie userPasswardCookie = new Cookie("password", passWord);
                        userNameCookie.setMaxAge(cookieTimeOut);
                        userPasswardCookie.setMaxAge(cookieTimeOut); //自定义到期时间,毫秒单位
                        userNameCookie.setPath(serverName);
                        userPasswardCookie.setPath(serverName);  //serverName一定要为项目名,不然一同路径又会生成cookie
                        HttpServletResponse resp = (HttpServletResponse) response;
                        resp.addCookie(userNameCookie);
                        resp.addCookie(userPasswardCookie);
                        System.out.println("保存cookie");
                        User user = userService.getByUserName(userName);
                        if (user != null) {
                            req.getSession().setAttribute("user", user);
                        }
                        req.getSession().setAttribute("userName", userName);
    

    若你的过滤器或拦截器不会拦截login页面请求(一般不会拦截),则需要在跳转到login页面的接口中,也加入如上代码。登录成功,存到cookie,session之后直接跳到index页面。若不成功则跳到login页面

    评论

报告相同问题?

悬赏问题

  • ¥15 outlook无法配置成功
  • ¥15 Pwm双极模式H桥驱动控制电机
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换