本文>. --><ehcache> <!-- Sets the path to the directory where cache .data files are created. If the path is a java System PRoperty it is replaced by its value in the running VM. The following properties are translated: user.home - User's home directory user.dir - User's current working directory java.io.tmpdir - Default temp file path --> <diskStore path="./target/tmp"/> <!--Default Cache configuration. These will applied to caches programmatically created through the CacheManager. The following attributes are required for defaultCache: maxInMemory - Sets the maximum number of objects that will be created in memory eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element is never expired. timeToIdleSeconds - Sets the time to idle for an element beforeQuery it expires. Is only used if the element is not eternal. Idle time is now - last accessed time timeToLiveSeconds - Sets the time to live for an element beforeQuery it expires. Is only used if the element is not eternal. TTL is now - creation time overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache has reached the maxInMemory limit. --> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" /> <!--Predefined caches. Add your cache configuration settings here. If you do not have a configuration for your cache a WARNING will be issued when the CacheManager starts The following attributes are required for defaultCache: name - Sets the name of the cache. This is used to identify the cache. It must be unique. maxInMemory - Sets the maximum number of objects that will be created in memory eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element is never expired. timeToIdleSeconds - Sets the time to idle for an element beforeQuery it expires. Is only used if the element is not eternal. Idle time is now - last accessed time timeToLiveSeconds - Sets the time to live for an element beforeQuery it expires. Is only used if the element is not eternal. TTL is now - creation time overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache has reached the maxInMemory limit. --> <!-- Sample cache named sampleCache1 This cache contains a maximum in memory of 10000 elements, and will expire an element if it is idle for more than 5 minutes and lives for more than 10 minutes. If there are more than 10000 elements it will overflow to the disk cache, which in this configuration will go to wherever java.io.tmp is defined on your system. On a standard linux system this will be /tmp" --> <cache name="sampleCache1" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true" /> <!-- Sample cache named sampleCache2 This cache contains 1000 elements. Elements will always be held in memory. They are not expired. --> <cache name="sampleCache2" maxElementsInMemory="1000" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false" /> --> <!-- Place configuration for your caches following --></ehcache>
第五步:在spring配置文件中配置shiro
<!-- shiro start --> <!-- 1. 配置SecurityManager --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="cacheManager" ref="cacheManager" /> <property name="authenticator" ref="authenticator"></property> <!-- 可以配置多個Realm,其實會把realms屬性賦值給ModularRealmAuthenticator的realms屬性 --> <property name="realms"> <list> <ref bean="userRealm" /> </list> </property> </bean> <!-- 2. 配置CacheManager --> <!-- 2.1 需要加入ehcache的jar包及配置文件 --> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <property name="cacheManagerConfigFile" value="classpath:ehcache.xml" /> </bean> <!-- 3. 配置Realm --> <!-- 3.1 直接配置繼承了org.apache.shiro.realm.AuthorizingRealm的bean --> <bean id="userRealm" class="com.ang.elearning.shiro.UserRealm"> <!-- 配置密碼匹配器 --> <property name="credentialsMatcher"> <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <!-- 加密算法為md5 --> <property name="hashAlgorithmName" value="MD5"></property> <!-- 加密次數 --> <property name="hashIterations" value="1024"></property> </bean> </property> </bean> <!-- 4. 配置LifecycleBeanPostProcessor,可以自定義地來調用配置在Spring IOC容器中shiro bean的生命周期方法 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> <!-- 5. 使能夠在IOC容器中使用shiro的注解,但必須在配置了LifecycleBeanPostProcessor之后才可以使用 --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor" /> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager" /> </bean> <!-- 6. 配置ShiroFilter --> <!-- 6.1 id必須和web.xml中配置的DelegatingFilterProxy的<filter-name>一致。 如果不一致,會拋出NoSuchBeanDefinitionException異常,因為shiro會在IOC容器中查找名稱和<filter-name> 值一致的filter bean --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <property name="loginUrl" value="/login.jsp" /> <property name="successUrl" value="/WEB-INF/user/index.jsp" /> <property name="unauthorizedUrl" value="/login.jsp" /> <!-- 配置哪些頁面需要受保護,以及訪問這些頁面需要的權限 --> <property name="filterChainDefinitions"> <value> <!-- 第一次匹配優先的原則 --> /login.jsp = anon /user/login = anon /logout = logout /** = authc </value> </property> </bean> <!-- 7. 配置ModularRealmAuthenticator,可以實現多Realm認證 --> <bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator"> <!-- 配置認證策略,只要有一個Realm認證成功即可,并且返回所有認證成功信息 --> <property name="authenticationStrategy"> <bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean> </property> </bean> <!-- shiro end -->第六步:測試(Userservice,UserDAO等略)
@Controller@RequestMapping("/user")public class UserController { @Resource private IUserService userService; @RequestMapping(value = "login", method = RequestMethod.POST) public String login(@RequestParam("email") String email, @RequestParam("passWord") String password) { Subject currentUser = SecurityUtils.getSubject(); if (!currentUser.isAuthenticated()) { UsernamePasswordToken upToken = new UsernamePasswordToken(email, password); upToken.setRememberMe(false); try { currentUser.login(upToken); return "user/index"; } catch (IncorrectCredentialsException ice) { System.out.println("郵箱/密碼不匹配!"); } catch (LockedAccountException lae) { System.out.println("賬戶已被凍結!"); } catch (AuthenticationException ae) { System.out.println(ae.getMessage()); } } return "redirect:/login.jsp"; }}login.jsp:
<form action="${pageContext.request.contextPath }/user/login" method="POST"> 郵箱:<input type="text" name="email"> <br><br> 密碼:<input type="password" name="password"> <br><br> <input type="submit" value="登錄"> </form>/WEB-INF/user/index.jsp
<h4>Login Successfully!</h4><br><a href="${pageContext.request.contextPath }/logout">Logout</a>補充: shiro中默認的過濾器:
整個認證流程: (1). 在Controller中通過Security.getSubject()獲取當前的Subject; (2). 通過Subject的isAuthenticated()驗證當前用戶是否已經被認證; (3). 如果沒有被認證,開始認證。 (4). 將從前臺傳來的用戶名(郵箱)和密碼封裝到一個UsernamePasswordToken對象upToken中; (5). 調用當前Subject的login(upToken)方法,這會把upToken作為參數傳遞到自定義的Realm的doGetAuthenticationInfo(AuthenticationToken)方法中; (6). 在doGetAuthenticationInfo(AuthenticationToken)方法中,首先將AuthenticationToken轉換為UsernamePasswordToken對象upToken,然后調用Service層,根據upToken中的用戶名到數據庫中查詢密碼; (7). 由shiro完成密碼的比對。密碼的比對是通過AuthenticatingRealm的credentialsMatcher屬性來進行比對的。
要實現特定Realm處理特定身份驗證的效果,請參見《shiro實現不同身份使用不同Realm進行驗證》
新聞熱點
疑難解答