shiro在springmvc里面的集成使用



shiro在springmvc里面的集成使用。

原文地址:http://peihexian.iteye.com/blog/2155516

需要在项目里面引入的maven依赖:

 

Xml代码  收藏代码
  1. <dependency>
  2.          <groupId>commons-collections</groupId>
  3.          <artifactId>commons-collections</artifactId>
  4.          <version>3.2.1</version>
  5.      </dependency>
  6.      <dependency>
  7.          <groupId>net.sf.ehcache</groupId>
  8.          <artifactId>ehcache-core</artifactId>
  9.          <version>2.6.9</version>
  10.      </dependency>
  11.      <dependency>
  12.          <groupId>org.apache.shiro</groupId>
  13.          <artifactId>shiro-spring</artifactId>
  14.          <version>1.2.3</version>
  15.      </dependency>
  16.      <dependency>
  17.          <groupId>org.apache.shiro</groupId>
  18.          <artifactId>shiro-ehcache</artifactId>
  19.          <version>1.2.3</version>
  20.      </dependency>
  21.      <dependency>
  22.          <groupId>org.apache.shiro</groupId>
  23.          <artifactId>shiro-quartz</artifactId>
  24.          <version>1.2.3</version>
  25.      </dependency>

 

如果项目是hibernate的,以前的时候ehcache可能不是单例的,因为shiro里面也使用到了ehcache做缓存,和hibernate的ehcache缓存配置有冲突,所以需要对hibernate的ehcache部分做些调整,调整如下:

 

Xml代码  收藏代码
  1. <bean id=”sessionFactory”
  2.          class=”org.springframework.orm.hibernate4.LocalSessionFactoryBean”>
  3.        <property name=”dataSource” ref=”dataSource”></property>
  4.        <property name=”hibernateProperties”>
  5.            <props>
  6.                <prop key=”hibernate.dialect”>org.hibernate.dialect.MySQLDialect</prop>
  7.                <prop key=”hibernate.show_sql”>true</prop>
  8.                <prop key=”hibernate.hbm2ddl.auto”>update</prop>
  9.                <!–
  10.                <prop key=”hibernate.cache.region.factory_class”>org.hibernate.cache.EhCacheRegionFactory</prop>
  11.                –>
  12.                <prop key=”hibernate.cache.region.factory_class”>
  13.                    org.hibernate.cache.SingletonEhCacheRegionFactory
  14.                </prop>
  15.                <prop key=”hibernate.cache.provider_class”>net.sf.ehcache.hibernate.SingletonEhCacheProvider</prop>
  16.                <prop key=”hibernate.cache.use_second_level_cache”>true</prop>
  17.                <prop key=”hibernate.cache.use_query_cache”>true</prop>
  18.                <prop key=”hibernate.cache.use_structured_entries”>true</prop>
  19.                <prop key=”hibernate.cache.provider_configuration_file_resource_path”>WEB-INF/classes/ehcache.xml</prop>
  20.                <prop key=”hibernate.current_session_context_class”>org.springframework.orm.hibernate4.SpringSessionContext</prop>
  21.            </props>
  22.        </property>
  23.        <property name=”packagesToScan”>
  24.            <list>
  25.                <value>com.xxx.entity</value>
  26.            </list>
  27.        </property>
  28.    </bean>

 

上面红色的文字部分是需要调整的内容。

 

 

既然用到了ehcache,ehcahce.xml文件里面的配置内容如下:

 

Xml代码  收藏代码
  1. <?xml version=”1.0″ encoding=”UTF-8″?>
  2. <ehcache>
  3.     <diskStore path=”java.io.tmpdir” />
  4.     <defaultCache maxElementsInMemory=”10000″ eternal=”false”
  5.                   timeToIdleSeconds=”120″ timeToLiveSeconds=”120″ overflowToDisk=”true” />
  6.     <cache name=”org.hibernate.cache.UpdateTimestampsCache”
  7.            maxElementsInMemory=”5000″ eternal=”true” overflowToDisk=”true” />
  8.     <cache name=”org.hibernate.cache.StandardQueryCache”
  9.            maxElementsInMemory=”10000″ eternal=”false” timeToLiveSeconds=”120″
  10.            overflowToDisk=”true” />
  11.     <!– 登录记录缓存 锁定10分钟 –>
  12.     <cache name=”passwordRetryCache”
  13.            maxEntriesLocalHeap=”2000″
  14.            eternal=”false”
  15.            timeToIdleSeconds=”3600″
  16.            timeToLiveSeconds=”0″
  17.            overflowToDisk=”false”
  18.            statistics=”true”>
  19.     </cache>
  20.     <cache name=”authorizationCache”
  21.            maxEntriesLocalHeap=”2000″
  22.            eternal=”false”
  23.            timeToIdleSeconds=”3600″
  24.            timeToLiveSeconds=”0″
  25.            overflowToDisk=”false”
  26.            statistics=”true”>
  27.     </cache>
  28.     <cache name=”authenticationCache”
  29.            maxEntriesLocalHeap=”2000″
  30.            eternal=”false”
  31.            timeToIdleSeconds=”3600″
  32.            timeToLiveSeconds=”0″
  33.            overflowToDisk=”false”
  34.            statistics=”true”>
  35.     </cache>
  36.     <cache name=”shiro-activeSessionCache”
  37.            maxEntriesLocalHeap=”2000″
  38.            eternal=”false”
  39.            timeToIdleSeconds=”3600″
  40.            timeToLiveSeconds=”0″
  41.            overflowToDisk=”false”
  42.            statistics=”true”>
  43.     </cache>
  44. </ehcache>

 

 

然后是web.xml文件里面加过滤器,注意要写在springmvc的filter前面

 

Xml代码  收藏代码
  1. <!– shiro 安全过滤器 –>
  2. <!– The filter-name matches name of a ’shiroFilter’ bean inside applicationContext.xml –>
  3. <filter>
  4.     <filter-name>shiroFilter</filter-name>
  5.     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  6.     <async-supported>true</async-supported>
  7.     <init-param>
  8.         <param-name>targetFilterLifecycle</param-name>
  9.         <param-value>true</param-value>
  10.     </init-param>
  11. </filter>
  12. <!– Make sure any request you want accessible to Shiro is filtered. /* catches all –>
  13. <!– requests.  Usually this filter mapping is defined first (before all others) to –>
  14. <!– ensure that Shiro works in subsequent filters in the filter chain:             –>
  15. <filter-mapping>
  16.     <filter-name>shiroFilter</filter-name>
  17.     <url-pattern>/*</url-pattern>
  18. </filter-mapping>

 

 

然后就是shiro相关的spring配置参数文件了

Xml代码  收藏代码
  1. <?xml version=”1.0″ encoding=”UTF-8″?>
  2. <beans xmlns=”http://www.springframework.org/schema/beans”
  3.        xmlns:util=”http://www.springframework.org/schema/util”
  4.        xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
  5.        xsi:schemaLocation=”
  6.        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  7.        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd”>
  8.     <!– 缓存管理器 使用Ehcache实现–>
  9.     <bean id=”cacheManager” class=”org.apache.shiro.cache.ehcache.EhCacheManager”>
  10.         <property name=”cacheManagerConfigFile” value=”classpath:ehcache.xml”/>
  11.     </bean>
  12.     <bean id=”passwordHelper” class=”com.shinowit.framework.security.PasswordHelper”>
  13.     </bean>
  14.     <!– 凭证匹配器 –>
  15.     <bean id=”credentialsMatcher”
  16.           class=”com.shinowit.framework.security.credentials.RetryLimitSimpleCredentialsMatcher”>
  17.         <constructor-arg ref=”cacheManager”/>
  18.         <property name=”passwordHelper” ref=”passwordHelper”/>
  19.     </bean>
  20.     <bean id=”shiro_user_dao” class=”com.shinowit.framework.security.dao.UserDAO”>
  21.         <property name=”jt” ref=”jdbcTemplate”/>
  22.     </bean>
  23.     <!– Realm实现 –>
  24.     <bean id=”userRealm” class=”com.shinowit.framework.security.realm.UserRealm”>
  25.         <property name=”userDAO” ref=”shiro_user_dao”/>
  26.         <property name=”credentialsMatcher” ref=”credentialsMatcher”/>
  27.         <!–密码校验接口–>
  28.         <property name=”cachingEnabled” value=”true”/>
  29.         <property name=”authenticationCachingEnabled” value=”true”/>
  30.         <property name=”authenticationCacheName” value=”authenticationCache”/>
  31.         <property name=”authorizationCachingEnabled” value=”true”/>
  32.         <property name=”authorizationCacheName” value=”authorizationCache”/>
  33.     </bean>
  34.     <!– 会话ID生成器 –>
  35.     <bean id=”sessionIdGenerator” class=”org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator”/>
  36.     <!– 会话Cookie模板 –>
  37.     <bean id=”sessionIdCookie” class=”org.apache.shiro.web.servlet.SimpleCookie”>
  38.         <constructor-arg value=”sid”/>
  39.         <property name=”httpOnly” value=”true”/>
  40.         <property name=”maxAge” value=”180000″/>
  41.     </bean>
  42.     <bean id=”rememberMeCookie” class=”org.apache.shiro.web.servlet.SimpleCookie”>
  43.         <constructor-arg value=”rememberMe”/>
  44.         <property name=”httpOnly” value=”true”/>
  45.         <property name=”maxAge” value=”2592000″/>
  46.         <!– 30天 –>
  47.     </bean>
  48.     <!– rememberMe管理器 –>
  49.     <bean id=”rememberMeManager” class=”org.apache.shiro.web.mgt.CookieRememberMeManager”>
  50.         <property name=”cipherKey”
  51.                   value=”#{T(org.apache.shiro.codec.Base64).decode(’4AvVhmFLUs0KTA3Kprsdag==’)}”/>
  52.         <property name=”cookie” ref=”rememberMeCookie”/>
  53.     </bean>
  54.     <!– 会话DAO –>
  55.     <bean id=”sessionDAO” class=”org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO”>
  56.         <property name=”activeSessionsCacheName” value=”shiro-activeSessionCache”/>
  57.         <property name=”sessionIdGenerator” ref=”sessionIdGenerator”/>
  58.     </bean>
  59.     <!– 会话验证调度器 –>
  60.     <bean id=”sessionValidationScheduler” class=”org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler”>
  61.         <property name=”sessionValidationInterval” value=”1800000″/>
  62.         <property name=”sessionManager” ref=”sessionManager”/>
  63.     </bean>
  64.     <!– 会话管理器 –>
  65.     <bean id=”sessionManager” class=”org.apache.shiro.web.session.mgt.DefaultWebSessionManager”>
  66.         <property name=”globalSessionTimeout” value=”1800000″/>
  67.         <property name=”deleteInvalidSessions” value=”true”/>
  68.         <property name=”sessionValidationSchedulerEnabled” value=”true”/>
  69.         <property name=”sessionValidationScheduler” ref=”sessionValidationScheduler”/>
  70.         <property name=”sessionDAO” ref=”sessionDAO”/>
  71.         <property name=”sessionIdCookieEnabled” value=”true”/>
  72.         <property name=”sessionIdCookie” ref=”sessionIdCookie”/>
  73.     </bean>
  74.     <!– 安全管理器 –>
  75.     <bean id=”securityManager” class=”org.apache.shiro.web.mgt.DefaultWebSecurityManager”>
  76.         <property name=”realm” ref=”userRealm”/>
  77.         <property name=”sessionManager” ref=”sessionManager”/>
  78.         <property name=”cacheManager” ref=”cacheManager”/>
  79.         <property name=”rememberMeManager” ref=”rememberMeManager”/>
  80.     </bean>
  81.     <!– 相当于调用SecurityUtils.setSecurityManager(securityManager) –>
  82.     <bean class=”org.springframework.beans.factory.config.MethodInvokingFactoryBean”>
  83.         <property name=”staticMethod” value=”org.apache.shiro.SecurityUtils.setSecurityManager”/>
  84.         <property name=”arguments” ref=”securityManager”/>
  85.     </bean>
  86.     <!–下面的loginUrl有两个必要条件,一个登陆校验失败以后会强制客户端redirect到这个url,
  87.     另外一个是登陆的表单(含有用户名及密码)必须action到这个url–>
  88.     <!– 自定义的能够接收校验码的身份验证过滤器
  89.      跳转问题太他妈诡异了,不用了,自己写代码控制如何跳转了
  90.     <bean id=”formAuthenticationFilter” class=”com.shinowit.framework.security.filter.ValidFormAuthenticationFilter”>
  91.         <property name=”usernameParam” value=”loginName”/>
  92.         <property name=”passwordParam” value=”loginPass”/>
  93.         <property name=”loginUrl” value=”/login/”/>
  94.     </bean>
  95. –>
  96.     <!– Shiro的Web过滤器 –>
  97.     <bean id=”shiroFilter” class=”org.apache.shiro.spring.web.ShiroFilterFactoryBean”>
  98.         <property name=”securityManager” ref=”securityManager”/>
  99.         <property name=”loginUrl” value=”/login/”/>
  100.         <property name=”unauthorizedUrl” value=”/unauthorized.jsp”/>
  101.         <property name=”filters”>
  102.             <map>
  103.                 <entry key=”authc”>
  104.                     <bean class=”org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter”/>
  105.                 </entry>
  106.             </map>
  107.             <!–
  108.             <util:map>
  109.                 <entry key=”authc” value-ref=”formAuthenticationFilter”/>
  110.             </util:map>
  111.             –>
  112.         </property>
  113.         <property name=”filterChainDefinitions”>
  114.             <value>
  115.                 /index.jsp = anon
  116.                 /validcode.jsp = anon
  117.                 /login/ = anon
  118.                 /static/** = anon
  119.                 /js/** = anon
  120.                 /img/** = anon
  121.                 /unauthorized.jsp = anon
  122.                 #/login/checklogin = authc
  123.                 /login/checklogin = anon
  124.                 /login/logoutlogout = logout
  125.                 /** = user
  126.             </value>
  127.         </property>
  128.     </bean>
  129.     <!– Shiro生命周期处理器–>
  130.     <bean id=”lifecycleBeanPostProcessor” class=”org.apache.shiro.spring.LifecycleBeanPostProcessor”/>
  131. </beans>

 

 

下面就是各种自己封装的java代码了

 

自定义的可以保存校验码的token类

Java代码  收藏代码
  1. package com.xxx.framework.security.token;
  2. import org.apache.shiro.authc.UsernamePasswordToken;
  3. /**
  4.  * Created on 2014/11/11.
  5.  */
  6. public class CustomUsernamePasswordToken extends UsernamePasswordToken {
  7.     //用于存储用户输入的校验码
  8.     private String validCode;
  9.     public CustomUsernamePasswordToken(String username, char[] password,boolean rememberMe, String host, String validCode) {
  10.         //调用父类的构造函数
  11.         super(username,password,rememberMe,host);
  12.         this.validCode=validCode;
  13.     }
  14.     public String getValidCode() {
  15.         return validCode;
  16.     }
  17.     public void setValidCode(String validCode) {
  18.         this.validCode = validCode;
  19.     }
  20. }

 


 

提供正确的登录用户信息的基于jdbc的realm

Java代码  收藏代码
  1. package com.xxx.framework.security.realm;
  2. import com.xxx.entity.SysUserEntity;
  3. import com.xxx.framework.security.dao.UserDAO;
  4. import com.xxx.framework.security.exception.ValidCodeException;
  5. import com.xxx.framework.security.token.CustomUsernamePasswordToken;
  6. import org.apache.log4j.Logger;
  7. import org.apache.shiro.SecurityUtils;
  8. import org.apache.shiro.authc.*;
  9. import org.apache.shiro.authz.AuthorizationInfo;
  10. import org.apache.shiro.authz.SimpleAuthorizationInfo;
  11. import org.apache.shiro.realm.AuthorizingRealm;
  12. import org.apache.shiro.subject.PrincipalCollection;
  13. public class UserRealm extends AuthorizingRealm {
  14.     private static Logger logger = Logger.getLogger(UserRealm.class);
  15.     private UserDAO userDAO;
  16.     public void setUserDAO(UserDAO userDAO) {
  17.         this.userDAO = userDAO;
  18.     }
  19.     @Override
  20.     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  21.         String username = (String) principals.getPrimaryPrincipal();
  22.         SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
  23.         authorizationInfo.setRoles(userDAO.getUserRoles(username));
  24.         authorizationInfo.setStringPermissions(userDAO.findPermissions(username));
  25.         return authorizationInfo;
  26.     }
  27.     @Override
  28.     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  29.         CustomUsernamePasswordToken login_token = (CustomUsernamePasswordToken) token;
  30.         //校验码判断逻辑
  31.         //取得用户输入的校验码
  32.         String userInputValidCode = login_token.getValidCode();
  33.         //取得真实的正确校验码
  34.         String realRightValidCode = (String) SecurityUtils.getSubject().getSession().getAttribute(“rand”);
  35.         if (null == userInputValidCode || !userInputValidCode.equalsIgnoreCase(realRightValidCode)) {
  36.             logger.debug(“验证码输入错误”);
  37.             throw new ValidCodeException(“验证码输入不正确”);
  38.         }
  39.         //以上校验码验证通过以后,查数据库
  40.         String username = (String) token.getPrincipal();
  41.         SysUserEntity user = userDAO.findByUsername(username);
  42.         if (user == null) {
  43.             throw new UnknownAccountException();//没找到帐号
  44.         }
  45.         if (Boolean.FALSE.equals(user.getValid())) {
  46.             throw new LockedAccountException(); //帐号锁定
  47.         }
  48.         //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以自定义实现
  49.         SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
  50.                 user.getLoginName(), //用户名
  51.                 user.getLoginPass(), //密码
  52.                 getName()  //realm name
  53.         );
  54.         return authenticationInfo;
  55.     }
  56.     @Override
  57.     public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
  58.         super.clearCachedAuthorizationInfo(principals);
  59.     }
  60.     @Override
  61.     public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
  62.         super.clearCachedAuthenticationInfo(principals);
  63.     }
  64.     @Override
  65.     public void clearCache(PrincipalCollection principals) {
  66.         super.clearCache(principals);
  67.     }
  68.     public void clearAllCachedAuthorizationInfo() {
  69.         getAuthorizationCache().clear();
  70.     }
  71.     public void clearAllCachedAuthenticationInfo() {
  72.         getAuthenticationCache().clear();
  73.     }
  74.     public void clearAllCache() {
  75.         clearAllCachedAuthenticationInfo();
  76.         clearAllCachedAuthorizationInfo();
  77.     }
  78. }

 

一个简单的自定义的处理校验码异常的类

 

Java代码  收藏代码
  1. package com.xxx.framework.security.exception;
  2. import org.apache.shiro.authc.AuthenticationException;
  3. /**
  4.  * Created on 2014/11/11.
  5.  */
  6. public class ValidCodeException extends AuthenticationException {
  7.     public ValidCodeException(String msg){
  8.         super(msg);
  9.     }
  10. }

 

查询用户信息及权限信息的dao

 

Java代码  收藏代码
  1. package com.xxx.framework.security.dao;
  2. import com.xxx.entity.SysUserEntity;
  3. import org.springframework.jdbc.core.BeanPropertyRowMapper;
  4. import org.springframework.jdbc.core.JdbcTemplate;
  5. import java.util.HashSet;
  6. import java.util.List;
  7. import java.util.Set;
  8. /**
  9.  * Created on 2014/11/10.
  10.  */
  11. public class UserDAO {
  12.     private JdbcTemplate jt;
  13.     public void setJt(JdbcTemplate jt) {
  14.         this.jt = jt;
  15.     }
  16.     public Set<String> getUserRoles(String loginName) {
  17.         String sql = ”select role from sys_user u, sys_role r,sys_user_to_role ur where u.login_name=? and u.user_code=ur.user_code and r.role_code=ur.role_code”;
  18.         return new HashSet(jt.queryForList(sql, String.class, loginName));
  19.     }
  20.     public Set<String> findPermissions(String loginName) {
  21.         String sql = ”select permission from sys_user u, sys_role r, sys_menu p, sys_user_to_role ur, sys_role_to_menu rp where u.login_name=? and u.user_code=ur.user_code and r.role_code=ur.role_code and r.role_code=rp.role_code and p.menu_id=rp.menu_id”;
  22.         return new HashSet(jt.queryForList(sql, String.class, loginName));
  23.     }
  24.     public SysUserEntity findByUsername(String loginName) {
  25.         String sql = ”select id, user_code,login_name, login_pass, valid from sys_user where login_name=?”;
  26.         List<SysUserEntity> userList = jt.query(sql, new BeanPropertyRowMapper(SysUserEntity.class), loginName);
  27.         if (userList.size() == 0) {
  28.             return null;
  29.         }
  30.         return userList.get(0);
  31.     }
  32. }

 

这个翻译过来叫啥合适呢?反正就是根据自定义的加密规则去进行密码匹配验证的类,爱JB叫啥叫啥吧

Java代码  收藏代码
  1. package com.xxx.framework.security.credentials;
  2. import com.xxx.framework.security.PasswordHelper;
  3. import com.xxx.framework.security.token.CustomUsernamePasswordToken;
  4. import org.apache.shiro.authc.AuthenticationInfo;
  5. import org.apache.shiro.authc.AuthenticationToken;
  6. import org.apache.shiro.authc.ExcessiveAttemptsException;
  7. import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
  8. import org.apache.shiro.cache.Cache;
  9. import org.apache.shiro.cache.CacheManager;
  10. import java.util.concurrent.atomic.AtomicInteger;
  11. public class RetryLimitSimpleCredentialsMatcher extends SimpleCredentialsMatcher {
  12.     private Cache<String, AtomicInteger> passwordRetryCache;
  13.     private PasswordHelper passwordHelper;
  14.     public RetryLimitSimpleCredentialsMatcher(CacheManager cacheManager) {
  15.         passwordRetryCache = cacheManager.getCache(“passwordRetryCache”);
  16.     }
  17.     public void setPasswordHelper(PasswordHelper passwordHelper) {
  18.         this.passwordHelper = passwordHelper;
  19.     }
  20.     @Override
  21.     public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
  22.         CustomUsernamePasswordToken login_token = (CustomUsernamePasswordToken) token;
  23.         String username = (String) token.getPrincipal();
  24.         //retry count + 1
  25.         AtomicInteger retryCount = passwordRetryCache.get(username);
  26.         if (retryCount == null) {
  27.             retryCount = new AtomicInteger(0);
  28.             passwordRetryCache.put(username, retryCount);
  29.         }
  30.         if (retryCount.incrementAndGet() > 5) {
  31.             //if retry count > 5 throw
  32.             throw new ExcessiveAttemptsException();
  33.         }
  34.         String user_input_login_pass = passwordHelper.encryptPassword(login_token.getUsername(), String.valueOf(login_token.getPassword()));
  35.         Object db_login_password = getCredentials(info);
  36.         //将密码加密与系统加密后的密码校验,内容一致就返回true,不一致就返回false
  37.         boolean matches = super.equals(user_input_login_pass, db_login_password);
  38.         if (matches) {
  39.             //clear retry count
  40.             passwordRetryCache.remove(username);
  41.         }
  42.         return matches;
  43.     }
  44. }

 

 

用户信息实体类

 

Java代码  收藏代码
  1. package com.xxx.entity;
  2. import javax.persistence.*;
  3. import java.util.List;
  4. /**
  5.  * Created on 2014/11/7.
  6.  * 系统用户信息
  7.  */
  8. @Entity
  9. @Table(name = ”sys_user”)
  10. public class SysUserEntity {
  11.     @GeneratedValue(strategy =GenerationType.IDENTITY)
  12.     @Column(name = ”id”,insertable = false,updatable = false)
  13.     private Integer id;
  14.     @Id
  15.     @Column(name = ”user_code”,length = 6)
  16.     private String userCode;
  17.     @Column(name = ”login_name”,length = 40,nullable = false,unique = true)
  18.     private String loginName;
  19.     @Column(name = ”login_pass”,length = 50)
  20.     private String loginPass;
  21.     @Column(name = ”address”,length = 200)
  22.     private String address;
  23.     @Column(name = ”telphone”,length = 30)
  24.     private String telPhone;
  25.     @Column(name = ”qq”,length = 15)
  26.     private String qq;
  27.     @Column(name = ”email”,length = 40)
  28.     private String email;
  29.     @Column(name = ”mobile”,length = 30)
  30.     private String mobile;
  31.     @Column(name = ”sort_id”)
  32.     private Short sortId;
  33.     @Column(name = ”valid”)
  34.     private Boolean valid;
  35.     @ManyToMany(fetch = FetchType.LAZY)
  36.     @JoinTable(name=”sys_user_to_role”,joinColumns = { @JoinColumn(name = ”user_code”) }, inverseJoinColumns = { @JoinColumn(name = ”role_code”)})
  37.     private List<SysRoleEntity> roleList;
  38.     public Integer getId() {
  39.         return id;
  40.     }
  41.     public void setId(Integer id) {
  42.         this.id = id;
  43.     }
  44.     public String getUserCode() {
  45.         return userCode;
  46.     }
  47.     public void setUserCode(String userCode) {
  48.         this.userCode = userCode;
  49.     }
  50.     public String getLoginName() {
  51.         return loginName;
  52.     }
  53.     public void setLoginName(String loginName) {
  54.         this.loginName = loginName;
  55.     }
  56.     public String getLoginPass() {
  57.         return loginPass;
  58.     }
  59.     public void setLoginPass(String loginPass) {
  60.         this.loginPass = loginPass;
  61.     }
  62.     public String getAddress() {
  63.         return address;
  64.     }
  65.     public void setAddress(String address) {
  66.         this.address = address;
  67.     }
  68.     public String getTelPhone() {
  69.         return telPhone;
  70.     }
  71.     public void setTelPhone(String telPhone) {
  72.         this.telPhone = telPhone;
  73.     }
  74.     public String getQq() {
  75.         return qq;
  76.     }
  77.     public void setQq(String qq) {
  78.         this.qq = qq;
  79.     }
  80.     public String getEmail() {
  81.         return email;
  82.     }
  83.     public void setEmail(String email) {
  84.         this.email = email;
  85.     }
  86.     public String getMobile() {
  87.         return mobile;
  88.     }
  89.     public void setMobile(String mobile) {
  90.         this.mobile = mobile;
  91.     }
  92.     public Short getSortId() {
  93.         return sortId;
  94.     }
  95.     public void setSortId(Short sortId) {
  96.         this.sortId = sortId;
  97.     }
  98.     public Boolean getValid() {
  99.         return valid;
  100.     }
  101.     public void setValid(Boolean valid) {
  102.         this.valid = valid;
  103.     }
  104.     public List<SysRoleEntity> getRoleList() {
  105.         return roleList;
  106.     }
  107.     public void setRoleList(List<SysRoleEntity> roleList) {
  108.         this.roleList = roleList;
  109.     }
  110. }

 

 

还有一个md5工具类

Java代码  收藏代码
  1. package com.xxx.framework.security;
  2. import java.security.MessageDigest;
  3. public class PasswordHelper {
  4.     /**
  5.      * 根据用户名与密码做md5单向hash加密
  6.      *
  7.      * @param username 用户名
  8.      * @param password 用户密码明文
  9.      * @return md5(username+password)
  10.      */
  11.     public String encryptPassword(String username, String password) {
  12.         String inStr = username + password;
  13.         MessageDigest md5 = null;
  14.         try {
  15.             md5 = MessageDigest.getInstance(“MD5″);
  16.         } catch (Exception e) {
  17.             System.out.println(e.toString());
  18.             e.printStackTrace();
  19.             return ”";
  20.         }
  21.         char[] charArray = inStr.toCharArray();
  22.         byte[] byteArray = new byte[charArray.length];
  23.         for (int i = 0; i < charArray.length; i++)
  24.             byteArray[i] = (byte) charArray[i];
  25.         byte[] md5Bytes = md5.digest(byteArray);
  26.         StringBuffer hexValue = new StringBuffer();
  27.         for (int i = 0; i < md5Bytes.length; i++) {
  28.             int val = ((int) md5Bytes[i]) & 0xff;
  29.             if (val < 16)
  30.                 hexValue.append(“0″);
  31.             hexValue.append(Integer.toHexString(val));
  32.         }
  33.         return hexValue.toString();
  34.     }
  35. }

 

 

好了,我们的springmvc controller类是这么写的

 

Java代码  收藏代码
  1. package com.xxx.web.login;
  2. import com.xxx.entity.SysUserEntity;
  3. import com.xxx.framework.dao.BaseDAO;
  4. import com.xxx.framework.security.PasswordHelper;
  5. import com.xxx.framework.security.exception.ValidCodeException;
  6. import com.xxx.framework.security.token.CustomUsernamePasswordToken;
  7. import org.apache.log4j.Logger;
  8. import org.apache.shiro.SecurityUtils;
  9. import org.apache.shiro.authc.ExcessiveAttemptsException;
  10. import org.apache.shiro.authc.IncorrectCredentialsException;
  11. import org.apache.shiro.authc.UnknownAccountException;
  12. import org.apache.shiro.authz.annotation.RequiresUser;
  13. import org.apache.shiro.subject.Subject;
  14. import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
  15. import org.apache.shiro.web.util.WebUtils;
  16. import org.springframework.stereotype.Controller;
  17. import org.springframework.web.bind.annotation.RequestMapping;
  18. import org.springframework.web.bind.annotation.RequestMethod;
  19. import org.springframework.web.bind.annotation.RequestParam;
  20. import org.springframework.web.bind.annotation.ResponseBody;
  21. import javax.annotation.Resource;
  22. import javax.servlet.http.HttpServletRequest;
  23. import javax.servlet.http.HttpSession;
  24. import java.util.HashMap;
  25. import java.util.Map;
  26. @Controller
  27. @RequestMapping(value = ”/login”)
  28. public class LoginController {
  29.     private static final Logger logger = Logger.getLogger(LoginController.class);
  30.     @Resource
  31.     private BaseDAO<SysUserEntity> sys_user_dao;
  32.     @RequestMapping(value = ”/”, method = RequestMethod.GET)
  33.     public String login() {
  34.         return ”/login/login”;
  35.     }
  36.     @RequestMapping(value = ”/checklogin”, method = RequestMethod.POST)
  37.     @ResponseBody
  38.     public Map<String, Object> checkLogin(SysUserEntity login_user,HttpServletRequest request,@RequestParam(“validCode”)String validCode) {
  39.         Map<String, Object> result = new HashMap<String, Object>();
  40.         result.put(“msg”, ”用户名或者密码错误!”);
  41.         result.put(“success”, ”true”);
  42.         result.put(“status”, false);
  43.         boolean rememberMe = WebUtils.isTrue(request, FormAuthenticationFilter.DEFAULT_REMEMBER_ME_PARAM);
  44.         String host = request.getRemoteHost();
  45.         //构造登陆令牌环
  46.         CustomUsernamePasswordToken token = new CustomUsernamePasswordToken(login_user.getLoginName(), login_user.getLoginPass().toCharArray(), rememberMe,host,validCode);
  47.         try{
  48.             //发出登陆请求
  49.             SecurityUtils.getSubject().login(token);
  50.             //登陆成功
  51.             HttpSession session = request.getSession(true);
  52.             try {
  53.                 SysUserEntity user = sys_user_dao.findOneEntityByHql(“from SysUserEntity where loginName=?”, login_user.getLoginName());
  54.                 if (null != user) {
  55.                     //根据输入的用户名和密码确实查到了用户信息
  56.                     session.removeAttribute(“rand”);
  57.                     session.setAttribute(“current_login_user”, user);
  58.                     result.put(“msg”, ”登录成功!”);
  59.                     result.put(“status”, true);
  60.                     result.put(“main_url”, ”http://” + request.getServerName() + ”:” + request.getServerPort() + request.getContextPath() + ”/main”);
  61.                 }
  62.             } catch (Exception e) {
  63.                 logger.error(e.getMessage(), e);
  64.             }
  65.             return  result;
  66.         }catch (UnknownAccountException e){
  67.             result.put(“msg”, ”账号不存在!”);
  68.         }catch (IncorrectCredentialsException e){
  69.             result.put(“msg”, ”用户名/密码错误!”);
  70.         }catch (ExcessiveAttemptsException e) {
  71.             result.put(“msg”, ”账户错误次数过多,暂时禁止登录!”);
  72.         }catch (ValidCodeException e){
  73.             result.put(“msg”, ”验证码输入错误!”);
  74.         }catch (Exception e){
  75.             result.put(“msg”, ”未知错误!”);
  76.         }
  77.         return result;
  78.     }
  79.     @RequestMapping(value=”/logout”)
  80.     public String logout(){
  81.         Subject currentUser = SecurityUtils.getSubject();
  82.         if (SecurityUtils.getSubject().getSession() != null)
  83.         {
  84.             currentUser.logout();
  85.         }
  86.         return ”redirect:/login/”;
  87.     }
  88.     @Resource
  89.     private PasswordHelper passwordHelper;
  90.     @RequestMapping(value = ”/fuck”)
  91.     @ResponseBody
  92.     public Map<String, Object> fuck() {
  93.         Map<String, Object> result = new HashMap<String, Object>();
  94.         result.put(“msg”, ”用户名或者密码错误!”);
  95.         result.put(“success”, ”true”);
  96.         result.put(“status”, false);
  97.         SysUserEntity user = sys_user_dao.findById(SysUserEntity.class, ”0001″);
  98.         user.setLoginPass(“a”);
  99.         String new_pass = passwordHelper.encryptPassword(user.getLoginName(), user.getLoginPass());
  100.         user.setLoginPass(new_pass);
  101.         sys_user_dao.update(user);
  102.         return result;
  103.     }
  104. }

 

哦,对了,里面那个fuck那个url是用来改密码的,因为数据库里面的密码是加密的,不这么整总也不可能知道对的md5值是多少。

 

但愿没有忘记什么内容,挺墨迹的,不过能跑起来以后后边关于权限和安全的处理就简单多了,写写注解或者标签就搞定了,很爽。