开发者社区> 问答> 正文

shiro报错 There is no session with id [xxx] ?报错

shiro报错There is no session with id [xxx] 

七月 06, 2015 3:06:03 下午 org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet [spring_mvc] in context with path [/Aladdin] threw exception [Request processing failed; nested exception is org.apache.shiro.session.UnknownSessionException: There is no session with id [e32a4c83-45e1-4e0f-809f-2e57851e3c6a]] with root cause
org.apache.shiro.session.UnknownSessionException: There is no session with id [e32a4c83-45e1-4e0f-809f-2e57851e3c6a]
	at org.apache.shiro.session.mgt.eis.AbstractSessionDAO.readSession(AbstractSessionDAO.java:170)
	at org.apache.shiro.session.mgt.eis.CachingSessionDAO.readSession(CachingSessionDAO.java:261)
	at org.apache.shiro.session.mgt.DefaultSessionManager.retrieveSessionFromDataSource(DefaultSessionManager.java:236)
	at org.apache.shiro.session.mgt.DefaultSessionManager.retrieveSession(DefaultSessionManager.java:222)
	at org.apache.shiro.session.mgt.AbstractValidatingSessionManager.doGetSession(AbstractValidatingSessionManager.java:118)
	at org.apache.shiro.session.mgt.AbstractNativeSessionManager.lookupSession(AbstractNativeSessionManager.java:105)
	at org.apache.shiro.session.mgt.AbstractNativeSessionManager.lookupRequiredSession(AbstractNativeSessionManager.java:109)
	at org.apache.shiro.session.mgt.AbstractNativeSessionManager.getAttribute(AbstractNativeSessionManager.java:206)
	at org.apache.shiro.session.mgt.DelegatingSession.getAttribute(DelegatingSession.java:141)
	at org.apache.shiro.session.ProxiedSession.getAttribute(ProxiedSession.java:121)
	at org.apache.shiro.session.ProxiedSession.getAttribute(ProxiedSession.java:121)
	at org.apache.shiro.subject.support.DelegatingSubject.getRunAsPrincipals(DelegatingSubject.java:452)
	at org.apache.shiro.subject.support.DelegatingSubject.<init>(DelegatingSubject.java:111)
	at org.apache.shiro.web.subject.support.WebDelegatingSubject.<init>(WebDelegatingSubject.java:60)
	at org.apache.shiro.web.mgt.DefaultWebSubjectFactory.createSubject(DefaultWebSubjectFactory.java:62)
	at org.apache.shiro.mgt.DefaultSecurityManager.doCreateSubject(DefaultSecurityManager.java:369)
	at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:344)
	at org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityManager.java:183)
	at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:283)
	at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:257)
	at com.word4one.hotel.pc.controller.CommercialController.commercialLogin(CommercialController.java:132)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
	at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
	at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
	at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
	at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:380)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1736)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1695)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Unknown Source)


PS:  本项目是 spring + shiro + mybatis

applicationContext.xml的配置

	<!-- 初始化认证策略 FirstSuccessfulStrategy:只要有一个Realm验证成功即可,只返回第一个Realm身份验证成功的认证信息,其他的忽略 -->
	<bean id="firstSuccess" class="org.apache.shiro.authc.pam.FirstSuccessfulStrategy"/>
	
	<!-- 设置认证策略 -->
	<bean id="modelAuthricator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
		<property name="authenticationStrategy" ref="firstSuccess"/>
	</bean>
	
	<!-- 继承自AuthorizingRealm的自定义Realm,即指定Shiro验证用户登录的类为自定义的ShiroDbRealm.java -->
	<bean id="commerRealm" class="com.word4one.hotel.realm.CommerRealm"></bean>
	<bean id="sysRealm" class="com.word4one.hotel.realm.SysRealm"></bean>
	<bean id="appRealm" class="com.word4one.hotel.realm.AppRealm"></bean>
	<bean id="saleRealm" class="com.word4one.hotel.realm.SaleRealm"></bean>
	<bean id="factoryUserRealm" class="com.word4one.hotel.realm.FactoryUserRealm"></bean>
	
	<!-- 启用缓存注解功能 -->
    <!-- <cache:annotation-driven cache-manager="cacheManager" /> -->
  	
  	<!-- 缓存管理器 使用Ehcache实现 -->  
	<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">  
	    <property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"/>  
	</bean>
	
	<!-- 配置权限管理器 -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		 <!-- 开启shiro session -->
		 <!-- <property name="sessionMode" value="native"/> -->
		 <!-- 配置启用认证策略 -->
		 <property name="authenticator" ref="modelAuthricator"/>
		 <!-- 启用多个realm -->
		 <property name="realms">
		 	<list>
		 		<ref bean="appRealm"/>
		 		<ref bean="commerRealm"/>
		 		<ref bean="sysRealm"/>
		 		<ref bean="saleRealm"/>
		 		<ref bean="factoryUserRealm"/>
			</list>
		 </property>
		 <!-- 启用缓存 -->
		 <property name="cacheManager" ref="cacheManager"/>
		 <!-- 启用会话管理器 -->
		 <property name="sessionManager" ref="sessionManager"/> 
		 <property name="rememberMeManager" ref="rememberMeManager"/>  
	</bean>
	
	<!-- 会话ID生成器 -->
    <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/>
	
    <!-- 会话Cookie模板 -->
    <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">  
        <constructor-arg value="sid"/>  
        <property name="httpOnly" value="true"/>  
        <property name="maxAge" value="180000"/>  
    </bean>  
  
    <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">  
        <constructor-arg value="rememberMe"/>  
        <property name="httpOnly" value="true"/>  
        <property name="maxAge" value="2592000"/>  
        <!-- 30天 -->  
    </bean>
    
    <!-- rememberMe管理器 -->  
    <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">  
        <property name="cipherKey"  
                  value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/>  
        <property name="cookie" ref="rememberMeCookie"/>  
    </bean>  
    
    <!-- 会话DAO -->  
    <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">  
        <property name="activeSessionsCacheName" value="shiro-activeSessionCache"/>  
        <property name="sessionIdGenerator" ref="sessionIdGenerator"/>  
    </bean>  
    
    <!-- 会话验证调度器 -->  
    <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler">  
        <property name="sessionValidationInterval" value="1800000"/>  
        <property name="sessionManager" ref="sessionManager"/>  
    </bean>
    
    <!-- 会话管理器 -->  
    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">  
        <property name="globalSessionTimeout" value="1800000"/>  
        <property name="deleteInvalidSessions" value="true"/>  
        <property name="sessionValidationSchedulerEnabled" value="true"/>  
        <property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>  
        <property name="sessionDAO" ref="sessionDAO"/>  
        <property name="sessionIdCookieEnabled" value="true"/>  
        <property name="sessionIdCookie" ref="sessionIdCookie"/>  
    </bean>
    
	<!--自定义的filter-->
	<bean id="roleOrFilter" class="com.word4one.hotel.filter.MyRolesAuthorizationFilter"></bean>
	
	<!-- Web应用中,Shiro可控制的Web请求必须经过Shiro主过滤器的拦截,Shiro对基于Spring的Web应用提供了完美的支持 -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<!-- Shiro的核心安全接口,这个属性是必须的 -->
		<property name="securityManager" ref="securityManager" />
		<!-- 要求登录时的链接(可根据项目的URL进行替换),非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 -->
		<!-- ps:检测到未登录(也就是未认证状态时),会被拦截到property中的配置页面 -->
		<!-- <property name="loginUrl" value="/" /> -->
		<!-- 登录成功后要跳转的连接 -->
		<!-- <property name="successUrl" value="/"/> -->
		<!-- 用户访问未对其授权的资源时,所显示的连接 -->
		<!-- ps:检测到角色,权限 不符时,会被拦截到property中配置的页面 -->
		<!-- <property name="unauthorizedUrl" value="/error.do" /> -->
		<property name="unauthorizedUrl" value="/error.jsp" />
		<!-- Shiro连接约束配置,即过滤链的定义 -->
		<!-- 下面value值的第一个'/'代表的路径是相对于HttpServletRequest.getContextPath()的值来的 -->
		<!-- anon:不指定过滤器,不错是这个过滤器是空的,什么都没做,跟没有一样 -->
		<!-- authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter -->
		<property name="filters">  
            <map>  
                <entry key="roleOrFilter" value-ref="roleOrFilter"/>
            </map>
        </property>  
		<property name="filterChainDefinitions">
			<value>
				<!-- 省略... -->
			</value>
		</property>
	</bean>

	<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />



web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  
  <!-- 防止发生java.beans.Introspector内存泄露,应将它配置在ContextLoaderListener的前面 -->  
  <!-- JDK中的java.beans.Introspector类的用途是发现Java类是否符合JavaBean规范  -->
  <listener>  
  	<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>  
  </listener> 
  
  <!-- 实例化Spring容器 -->  
  <!-- 应用启动时,该监听器被执行,它会读取Spring相关配置文件,其默认会到WEB-INF中查找applicationContext.xml -->  
  <listener>  
  	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
  </listener> 
  
  <!-- 配置Shiro过滤器,先让Shiro过滤系统接收到的请求 -->
  <!-- 这里filter-name必须对应applicationContext.xml中定义的<bean id="shiroFilter"/> -->
  <!-- 使用[/*]匹配所有请求,保证所有的可控请求都经过Shiro的过滤 -->
  <!-- 通常会将此filter-mapping放置到最前面(即其他filter-mapping前面),以保证它是过滤器链中第一个起作用的 -->
  <filter>
  	<filter-name>shiroFilter</filter-name>
	<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
		<init-param>
			<!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 -->
			<param-name>targetFilterLifecycle</param-name>
			<param-value>true</param-value>
		</init-param>
  </filter>
  <filter-mapping>
		<filter-name>shiroFilter</filter-name>
		<url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <filter>    
    <filter-name>encodingFilter</filter-name>    
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>    
    <init-param>    
        <param-name>encoding</param-name>    
        <param-value>UTF-8</param-value>    
    </init-param>    
    <init-param>    
        <param-name>forceEncoding</param-name>    
        <param-value>true</param-value>    
    </init-param>    
  </filter>    
    
  <filter-mapping>    
  	<filter-name>encodingFilter</filter-name>    
    <url-pattern>/*</url-pattern>    
  </filter-mapping>
  
  <!-- 检测登录过滤器 
  	         检测到未登录状态(为检测到session)拦截回登录首页 -->
  <filter>
  	<filter-name>loginFilter</filter-name>
  	<filter-class>com.word4one.hotel.filter.LoginFilter</filter-class>
  </filter>
  <filter-mapping>
	<filter-name>loginFilter</filter-name>
	<url-pattern>/jsp/system/show.jsp</url-pattern>
  </filter-mapping>
 
  <!-- 注册servlet节点,容器启动时,加载spring框架 -->
  <servlet>
    <servlet-name>spring_mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- <servlet-class>com.xxx.util.MyDispatcherServlet</servlet-class> 
    	自定义核心控制器  MyDispatcherServelet 继承 DispatcherServlet 用来处理请求编码
    -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/applicationContext.xml</param-value>
    </init-param>
  </servlet>
  
  <!-- 注册servlet-mapping节点  设置spring_mvc处理请求类型*.do-->
  <servlet-mapping>
    <servlet-name>spring_mvc</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <error-page>  
      <error-code>405</error-code>  
      <location>/WEB-INF/405.jsp</location>  
  </error-page>  
  <error-page>  
      <error-code>404</error-code>  
      <location>/WEB-INF/404.jsp</location>  
  </error-page>  
  <error-page>  
      <error-code>500</error-code>  
      <location>/WEB-INF/500.jsp</location>  
  </error-page>
  
</web-app>



controller登录代码片段

@RequestMapping("/jsp/system/systemUserLogin")
	public String systemUserLogin(SystemUserForm systemUserForm, HttpSession session,
			HttpServletRequest request) {

		System.out.println("系统用户登录...");
		// 失败后的跳转路径
		String resultPageURL = "redirect:/";
		// 接收提交表单项
		String username = systemUserForm.getUsername();
		String password = systemUserForm.getPassword();
		String validatecode = systemUserForm.getValidatecode();
		// 获取session中的验证码
		String checkcode = (String) session.getAttribute("key");
		System.out.println("用户[" + username + "]登录时输入的验证码为[" + validatecode + "],HttpSession中的验证码为[" + checkcode + "]");  
		// 判断验证码是否一致
		if (checkcode != null && checkcode.equalsIgnoreCase(validatecode)) {
			session.removeAttribute("key");
			//生成基于用户名和密码的令牌
			UsernamePasswordToken token = new UsernamePasswordToken(username, AESUtils.encrypt(AESUtils.SEED, password));  
			//token.setRememberMe(true);
		    System.out.println("为了验证登录用户而封装的token为" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));  
		    //获取当前的Subject  
	        Subject currentUser = SecurityUtils.getSubject();
	        try {
	        	//尝试登录
	        	currentUser.login(token); 
	        	//验证是否登录成功  
		        if(currentUser.isAuthenticated()){  
		            System.out.println("用户[" + username + "]登录认证通过 ...");
		            return "redirect:/jsp/system/show.jsp";
		        }else{  
		            token.clear(); 
		            return resultPageURL;
		        }
	        }catch(UnknownAccountException uae){  
	            System.out.println("对用户[" + username + "]进行登录验证..验证未通过,未知账户");  
	            request.setAttribute("message_login", "未知账户");  
	        }catch(IncorrectCredentialsException ice){  
	            System.out.println("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证");  
	            request.setAttribute("message_login", "密码不正确");  
	        }catch(LockedAccountException lae){  
	            System.out.println("对用户[" + username + "]进行登录验证..验证未通过,账户已锁定");  
	            request.setAttribute("message_login", "账户已锁定");  
	        }catch(ExcessiveAttemptsException eae){  
	            System.out.println("对用户[" + username + "]进行登录验证..验证未通过,错误次数过多");  
	            request.setAttribute("message_login", "用户名或密码错误次数过多");  
	        }catch(AuthenticationException ae){  
	            //通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景  
	            System.out.println("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下");  
	            ae.printStackTrace();  
	            request.setAttribute("message_login", "用户名或密码不正确");  
	        }
	        //用户名,密码验证失败跳转...
	        return resultPageURL;
		}
		//验证码失败跳转...
		return resultPageURL;
}



对应realm文件代码片段

package com.word4one.hotel.realm;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

import com.word4one.hotel.bean.DicBean;
import com.word4one.hotel.bean.Permission;
import com.word4one.hotel.bean.SystemUser;
import com.word4one.hotel.service.DicBeanService;
import com.word4one.hotel.service.PermissionService;
import com.word4one.hotel.service.SystemUserService;
import com.word4one.hotel.util.RoleDescriptionUtil;

public class SysRealm extends AuthorizingRealm{

	@Autowired
	private SystemUserService systemUserService;
	@Autowired
	private DicBeanService dicBeanService;
	@Autowired
	private PermissionService permissionService;
	
	
	
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		
		System.out.println("登录之后,做任何操作-先取得角色权限<为系统用户授权>......");
		//获取当前登录的用户名
		String currentUsername = (String)super.getAvailablePrincipal(principals);
		System.out.println(currentUsername + "...........");
		//创建角色列表集合
		List<String> roleList = new ArrayList<String>();
		System.out.println(roleList + "roleList.......");
		//创建权限列表集合
		List<String> premissionList = new ArrayList<String>();
		System.out.println(roleList + "premissionList........"); 
		
		//授权核心业务逻辑
		try {
			//从数据库中获取当前登录用户的详细信息  
			SystemUser systemUser = systemUserService.getSystemUserByUsername(currentUsername);
			if(systemUser != null){
				//根据role_id判断 系统用户身份:<系统管理员 or 业务员>
				if(systemUser.getRole_id() == RoleDescriptionUtil.ROLE_2){
					System.out.println("正在为<" + systemUser.getUsername() + ">系统管理员---授权中---");
				}else if(systemUser.getRole_id() == RoleDescriptionUtil.ROLE_4){
					System.out.println("正在为<" + systemUser.getUsername() + ">业务员---授权中---");
				}
				//根据当前登录role_id,查询tb_dic得到role
				DicBean dicBean = dicBeanService.getRoleByRoleId(systemUser.getRole_id());
				if(dicBean != null){
					System.out.println("roleName:--" + dicBean.getValue());
					roleList.add(dicBean.getValue());
				}
				//根据当前登录role_id,查询permission得到requestName
				List<Permission> permissions = permissionService.getPermissionByRoleId(systemUser.getRole_id());
				if(permissions.size() != 0){
					for(Permission perm : permissions){
						System.out.println("permissionName:--" + perm.getRequestName());
						premissionList.add(perm.getRequestName());
					}
				}
			}else{
				//throw new AuthorizationException();
				System.out.println("授权用户验证失败,不是系统用户...<<无法授权!!!>>");
			}
			
			System.out.println("-----开始当前用户[" + currentUsername + "]授权-------");
			//为当前用户设置角色和权限  
			SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();  
			simpleAuthorInfo.addRoles(roleList);  
			simpleAuthorInfo.addStringPermissions(premissionList);
			System.out.println("-----结束当前用户[" + currentUsername + "]授权-------");
			return simpleAuthorInfo;
			
		} catch (Exception e) {
			e.printStackTrace();
			//记录日志,系统异常
		}
		// 若该方法什么都不做直接返回null的话,就会导致任何用户访问时都会自动跳转到unauthorizedUrl指定的地址
		// 详见applicationContext.xml中的<bean id="shiroFilter">的配置
		return null;
	}

	
	
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authcToken) throws AuthenticationException {
			
		System.out.println("<-- 系统用户 -->该方法的调用时机为 sys Subject.login()时");
		// 获取基于用户名和密码的令牌
		// 实际上这个authcToken是从SystemUserController里面currentUser.login(token)传过来的
		// 两个token的引用都是一样的
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		System.out.println("<-- 系统用户 -->验证当前Subject时获取到token为" + ReflectionToStringBuilder.toString(token,ToStringStyle.MULTI_LINE_STYLE));
		//验证后台用户登录
		try {
			//封装数据
			SystemUser systemUser = new SystemUser();
			systemUser.setUsername(token.getUsername());
			systemUser.setPassword(new String(token.getPassword()));
			//后台用户登录
			SystemUser sysUser = systemUserService.getSystemUserByUsernameAndPwd(systemUser);
			if(sysUser != null){
				AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(sysUser.getUsername(),sysUser.getPassword(),this.getName());
				System.out.println("后台用户: " + sysUser.getUsername() + "认证成功...");
				systemUserService.modifyLasttime2SystemUser(sysUser);
				System.out.println("后续数据初始化成功...");
				this.setSession("sysUser", sysUser);
				return authcInfo;
			}else{
				// 没有返回登录用户名对应的SimpleAuthenticationInfo对象时,就会抛出UnknownAccountException异常
				System.out.println("后台用户登录败以后走的这里...");
				return null;
			}
		} catch(SQLException sqlException){
			sqlException.printStackTrace();
			//记录日志,系统异常,数据库异常
		} catch (Exception e) {
			e.printStackTrace();
			//记录日志,系统异常
		}
		return null;
	}

	/**
	 * @author yh
	 * time : 2014-11-24
	 * content :
	 * 将一些数据放到ShiroSession中,以便于其它地方使用
	 * 在Controller中,使用时直接用HttpSession.getAttribute(key)就可以取到
	 */
	private void setSession(Object key, Object value) {
		Subject currentUser = SecurityUtils.getSubject();
		if (null != currentUser) {
			Session session = currentUser.getSession();
			System.out.println("Session默认超时时间为[" + session.getTimeout() + "]毫秒");
			if (null != session) {
				session.setAttribute(key, value);
			}
		}
	}
}




小生实在搞不明白,shiro中的session会话. 

在不启用session会话配置时,程序运行一切正常.

若使用shiro 中的 session会话,为何启用就会报错.

不明白其中原理.

展开
收起
爱吃鱼的程序员 2020-06-14 14:52:58 897 0
1 条回答
写回答
取消 提交回答
  • https://developer.aliyun.com/profile/5yerqm5bn5yqg?spm=a2c6h.12873639.0.0.6eae304abcjaIB

    Sessionsession=currentUser.getSession();

    这里的session是否是shironative的session

    这里的session是否是shironative的session??

    什么意思!!

    shiro本身的bug

    有解么。。。
    请问这个问题解决了吗?如何解决的?可以分享下吗 shiro本身的bug

    确认一下是不是这个问题导致的:

    https://www.v2ex.com/t/56219

    这个也许对你有点用:

    解决方法:

    <beanid="sessionManager"class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
          <!--设置session过期时间为1小时(单位:毫秒),默认为30分钟-->
          <propertyname="globalSessionTimeout"value="3600000"></property>
          <propertyname="sessionValidationSchedulerEnabled"value="true"></property>
           <propertyname="sessionIdCookie">
           <beanclass="org.apache.shiro.web.servlet.SimpleCookie">
             <propertyname="name"value="JSESSID"/>
           </bean>
         </property>
       </bean>

    2020-06-14 14:53:16
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
Apache Wicket User Guide - Ref 立即下载
低代码开发师(初级)实战教程 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载