欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

shiro关于session id无效的问题 , 跪求大神解惑

程序员文章站 2022-05-03 10:02:12
...


转载地址:https://ask.csdn.net/questions/687679

最近重构之前的老系统springMVC转springBoot+shiro遇到了session id无效的问题
shiroConfig里面也已经配置了自定义sessionId
ShiroConfig代码如下

 @Configuration
public class ShiroConfig {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.password}")
    private String password;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${session.sessionTimeout}")
    private long sessionTimeout;

    @Value("${session.sessionTimeoutClean}")
    private long sessionTimeoutClean;

    @Value("${shiro.session.expire}")
    private Integer expire;

    @Bean
    public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 如果不设置默认会自动寻找Web工程根目录下的"/login"页面
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/loginSuccess");
        //未授权界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/error/403");

        //拦截器.
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        filterChainDefinitionMap.put("/3rd/**", "anon");
        filterChainDefinitionMap.put("/framework/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/font/**", "anon");
        //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
        filterChainDefinitionMap.put("/logout", "logout");
        filterChainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //设置realm.
        securityManager.setRealm(myShiroRealm());
        // 自定义缓存实现 使用redis
        // securityManager.setCacheManager(redisCacheManager());
        // 自定义session管理 使用redis
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }

    @Bean
    public MyShiroRealm myShiroRealm() {
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return myShiroRealm;
    }

    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("SHA-1");//散列算法:这里使用MD5算法;
        hashedCredentialsMatcher.setHashIterations(1024);//散列的次数,比如散列两次,相当于 md5(md5(""));
        return hashedCredentialsMatcher;
    }

    /**
     * 开启shiro aop注解支持.
     * 使用代理方式;所以需要开启代码支持;
     *
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    /**
     * 配置shiro redisManager
     * 使用的是shiro-redis开源插件
     *
     * @return
     */
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(host);
        redisManager.setPort(port);
        redisManager.setExpire(1800);// 配置缓存过期时间 30分钟
        redisManager.setTimeout(timeout);
        redisManager.setPassword(password);
        return redisManager;
    }

    /**
     * RedisSessionDAO shiro sessionDao层的实现 通过redis
     * 使用的是shiro-redis开源插件
     */
    @Bean
    public RedisSessionDAO redisSessionDAO() {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        redisSessionDAO.setSessionIdGenerator(sessionIdGenerator());
        redisSessionDAO.setKeyPrefix("shiro_session_");
        return redisSessionDAO;
    }

    /**
     * shiro session的管理
     */
    @Bean
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionDAO(redisSessionDAO());
        // 会话超时时间,单位:毫秒
        sessionManager.setGlobalSessionTimeout(sessionTimeout);
        // 定时清理失效会话, 清理用户直接关闭浏览器造成的孤立会话
        sessionManager.setSessionValidationInterval(sessionTimeoutClean);
        sessionManager.setSessionValidationSchedulerEnabled(true);
        // 指定sessionid
        sessionManager.setSessionIdCookie(sessionIdCookie());
        sessionManager.setSessionIdCookieEnabled(true);
        // 去掉shiro登录时url里的JSESSIONID
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        return sessionManager;
    }

    /**
     * 指定本系统sessionid, 问题: 与servlet容器名冲突, 如jetty, tomcat 等默认jsessionid,
     * 当跳出shiro servlet时如error-page容器会为jsessionid重新分配值导致登录会话丢失!
     *
     * @return
     */
    @Bean
    public SimpleCookie sessionIdCookie() {
        SimpleCookie simpleCookie = new SimpleCookie();
        simpleCookie.setName("shiro.session");
        return simpleCookie;
    }

    @Bean
    public SessionIdGenerator sessionIdGenerator() {
        SessionIdGenerator sessionIdGenerator = new SessionIdGenerator() {
            @Override
            public Serializable generateId(Session session) {
                return IdGen.uuid();
            }
        };
        return sessionIdGenerator;
    }


}

LoginController代码如下

 @Controller
public class LoginController {

    @Value("${login.adauth}")
    private String adAuth;

    /**
     * 管理登录 浏览器访问 系统
     */
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login(HttpServletRequest request, HttpServletResponse response, Model model) {
        User user = UserUtils.getUser();
        // 如果已经登录,则跳转到管理首页
        if (!StringUtils.isNullOrEmpty(user.getId())) {
            return "redirect:/loginSuccess";
        }
        model.addAttribute("login_adauth", adAuth);
        model.addAttribute("domain", 0);

        return "sys/sysLogin";
    }

    /**
     * 登录失败,真正登录的POST请求由Filter完成
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(@RequestParam(FormAuthenticationFilter.DEFAULT_USERNAME_PARAM) String username, String password, HttpServletRequest request, HttpServletResponse response, Model model) {
        User user = UserUtils.getUser();
        // 如果已经登录,则跳转到管理首页
        if (!StringUtils.isNullOrEmpty(user.getId())) {
            return "redirect:/loginSuccess";
        }
        model.addAttribute(FormAuthenticationFilter.DEFAULT_USERNAME_PARAM, username);
        model.addAttribute("login_adauth", adAuth);
        model.addAttribute("domain", 1);
        return "sys/sysLogin";
    }

    /**
     * 登录成功,进入管理首页
     */
    @RequestMapping(value = "/loginSuccess")
    public String index(HttpServletRequest request, HttpServletResponse response, Model model) {
        User user = UserUtils.getUser();
        // 未登录,则跳转到登录页
        if (StringUtils.isNullOrEmpty(user.getId())) {
            return "redirect:/login";
        }
        model.addAttribute("user", user);
        model.addAttribute("login_adauth", adAuth);
        return "sys/sysIndex";
    }

}

sysLogin代码如下

 <div class="login">
            <div class="loginlogo"></div>
            <form id="login" action="/login" method="post">
                <input type="text" id="username" name="username" class="name" placeholder="User name" />
                <input type="password" id="password" name="password" class="pwd" placeholder="Password" />
                <div class="w_info" id="error_info">The user name error, please try again</div>
                <input type="submit" value="Login" class="submit" />
                <div class="tipsDiv" style="text-align: center;">
                <a style="color: #fff;" href="http://workplace.lenovo.com/SoftwareDetail?id=93">Chrome Download</a>
                </div>
            </form>
        </div>

问题是浏览器输入http://127.0.0.1/login访问正常 , 登录也正常
shiro关于session id无效的问题 , 跪求大神解惑

如果我浏览器里面直接输入http://127.0.0.1访问就废了 , 看图
shiro关于session id无效的问题 , 跪求大神解惑
LoginController里面的login get方法也正常走 一到返回页面就是上面的错
shiro关于session id无效的问题 , 跪求大神解惑

跪求大神解惑

相关标签: shiro id无效