当传说遇上神话 2018-05-02 11:05 采纳率: 0%
浏览 7542
已结题

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

最近重构之前的老系统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访问正常 , 登录也正常
访问正常的

如果我浏览器里面直接输入http://127.0.0.1访问就废了 , 看图
图片说明
LoginController里面的login get方法也正常走 一到返回页面就是上面的错
图片说明

跪求大神解惑

  • 写回答

2条回答

  • 偏偏喜欢你 2018-05-02 11:09
    关注

    LoginController里面的login get方法也正常走 一到返回页面就是上面的错

    评论

报告相同问题?

悬赏问题

  • ¥15 slam rangenet++配置
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制
  • ¥20 usb设备兼容性问题
  • ¥15 错误(10048): “调用exui内部功能”库命令的参数“参数4”不能接受空数据。怎么解决啊