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访问正常 , 登录也正常
如果我浏览器里面直接输入http://127.0.0.1访问就废了 , 看图
LoginController里面的login get方法也正常走 一到返回页面就是上面的错
跪求大神解惑