在SSM中使用shiro实现登录验证(附密码加密)

2/22/2017来源:ASP.NET技巧人气:2850

本文>. --> <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进行验证》