shiro在springmvc,hibernate,ehcache里面的集成使用

本文介绍如何在Spring MVC项目中整合Shiro与EhCache进行权限管理和缓存优化,包括配置细节与自定义组件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

<bean id="sessionFactory"
      class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.hbm2ddl.auto">update</prop>
          <!--
        <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.EhCacheRegionFactory</prop>
        -->
        <prop key="hibernate.cache.region.factory_class">
          org.hibernate.cache.SingletonEhCacheRegionFactory
        </prop>
        <prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.SingletonEhCacheProvider</prop>
        <prop key="hibernate.cache.use_second_level_cache">true</prop>
        <prop key="hibernate.cache.use_query_cache">true</prop>
        <prop key="hibernate.cache.use_structured_entries">true</prop>
        <prop key="hibernate.cache.provider_configuration_file_resource_path">WEB-INF/classes/ehcache.xml</prop>
        <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop>
      </props>
    </property>
    <property name="packagesToScan">
      <list>
        <value>com.xxx.entity</value>
      </list>
    </property>
  </bean>

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

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

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <diskStore path="java.io.tmpdir" />

    <defaultCache maxElementsInMemory="10000" eternal="false"
        timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" />
    <cache name="org.hibernate.cache.UpdateTimestampsCache"
      maxElementsInMemory="5000" eternal="true" overflowToDisk="true" />
    <cache name="org.hibernate.cache.StandardQueryCache"
      maxElementsInMemory="10000" eternal="false" timeToLiveSeconds="120"
      overflowToDisk="true" />
    <!-- 登录记录缓存 锁定10分钟 -->
    <cache name="passwordRetryCache"
      maxEntriesLocalHeap="2000"
      eternal="false"
      timeToIdleSeconds="3600"
      timeToLiveSeconds="0"
      overflowToDisk="false"
      statistics="true">
    </cache>

    <cache name="authorizationCache"
      maxEntriesLocalHeap="2000"
      eternal="false"
      timeToIdleSeconds="3600"
      timeToLiveSeconds="0"
      overflowToDisk="false"
      statistics="true">
    </cache>

    <cache name="authenticationCache"
      maxEntriesLocalHeap="2000"
      eternal="false"
      timeToIdleSeconds="3600"
      timeToLiveSeconds="0"
      overflowToDisk="false"
      statistics="true">
    </cache>

    <cache name="shiro-activeSessionCache"
      maxEntriesLocalHeap="2000"
      eternal="false"
      timeToIdleSeconds="3600"
      timeToLiveSeconds="0"
      overflowToDisk="false"
      statistics="true">
    </cache>
</ehcache>

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

<!-- shiro 安全过滤器 -->
  <!-- The filter-name matches name of a 'shiroFilter' bean inside applicationContext.xml -->
  <filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <async-supported>true</async-supported>
    <init-param>
      <param-name>targetFilterLifecycle</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>

  <!-- Make sure any request you want accessible to Shiro is filtered. /* catches all -->
  <!-- requests.  Usually this filter mapping is defined first (before all others) to -->
  <!-- ensure that Shiro works in subsequent filters in the filter chain:			 -->
  <filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

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

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:util="http://www.springframework.org/schema/util"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="
     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
     http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

  <!-- 缓存管理器 使用Ehcache实现-->
  <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
    <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/>
  </bean>

  <bean id="passwordHelper" class="com.shinowit.framework.security.PasswordHelper">
  </bean>

  <!-- 凭证匹配器 -->
  <bean id="credentialsMatcher"
      class="com.shinowit.framework.security.credentials.RetryLimitSimpleCredentialsMatcher">
    <constructor-arg ref="cacheManager"/>
    <property name="passwordHelper" ref="passwordHelper"/>
  </bean>


  <bean id="shiro_user_dao" class="com.shinowit.framework.security.dao.UserDAO">
    <property name="jt" ref="jdbcTemplate"/>
  </bean>

  <!-- Realm实现 -->
  <bean id="userRealm" class="com.shinowit.framework.security.realm.UserRealm">
    <property name="userDAO" ref="shiro_user_dao"/>
    <property name="credentialsMatcher" ref="credentialsMatcher"/>
    <!--密码校验接口-->
    <property name="cachingEnabled" value="true"/>
    <property name="authenticationCachingEnabled" value="true"/>
    <property name="authenticationCacheName" value="authenticationCache"/>
    <property name="authorizationCachingEnabled" value="true"/>
    <property name="authorizationCacheName" value="authorizationCache"/>
  </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>

  <!-- 安全管理器 -->
  <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="realm" ref="userRealm"/>
    <property name="sessionManager" ref="sessionManager"/>
    <property name="cacheManager" ref="cacheManager"/>
    <property name="rememberMeManager" ref="rememberMeManager"/>
  </bean>

  <!-- 相当于调用SecurityUtils.setSecurityManager(securityManager) -->
  <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
    <property name="arguments" ref="securityManager"/>
  </bean>

  <!--下面的loginUrl有两个必要条件,一个登陆校验失败以后会强制客户端redirect到这个url,
  另外一个是登陆的表单(含有用户名及密码)必须action到这个url-->
  <!-- 自定义的能够接收校验码的身份验证过滤器
   跳转问题太他妈诡异了,不用了,自己写代码控制如何跳转了
  <bean id="formAuthenticationFilter" class="com.shinowit.framework.security.filter.ValidFormAuthenticationFilter">
    <property name="usernameParam" value="loginName"/>
    <property name="passwordParam" value="loginPass"/>
    <property name="loginUrl" value="/login/"/>
  </bean>
-->

  <!-- Shiro的Web过滤器 -->
  <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager"/>
    <property name="loginUrl" value="/login/"/>
    <property name="unauthorizedUrl" value="/unauthorized.jsp"/>
    <property name="filters">
      <map>
        <entry key="authc">
          <bean class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter"/>
        </entry>
      </map>
      <!--
      <util:map>
        <entry key="authc" value-ref="formAuthenticationFilter"/>
      </util:map>
      -->
    </property>
    <property name="filterChainDefinitions">
      <value>
        /index.jsp = anon
        /validcode.jsp = anon
        /login/ = anon
        /static/** = anon
        /js/** = anon
        /img/** = anon
        /unauthorized.jsp = anon
        #/login/checklogin = authc
        /login/checklogin = anon
        /login/logout = logout
        /** = user
      </value>
    </property>
  </bean>

  <!-- Shiro生命周期处理器-->
  <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>


</beans>

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

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

package com.xxx.framework.security.token;

import org.apache.shiro.authc.UsernamePasswordToken;

/**
 * Created on 2014/11/11.
 */
public class CustomUsernamePasswordToken extends UsernamePasswordToken {

  //用于存储用户输入的校验码
  private String validCode;


  public CustomUsernamePasswordToken(String username, char[] password,boolean rememberMe, String host, String validCode) {
    //调用父类的构造函数
    super(username,password,rememberMe,host);
    this.validCode=validCode;
  }

  public String getValidCode() {
    return validCode;
  }

  public void setValidCode(String validCode) {
    this.validCode = validCode;
  }
}

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

package com.xxx.framework.security.realm;

import com.xxx.entity.SysUserEntity;
import com.xxx.framework.security.dao.UserDAO;
import com.xxx.framework.security.exception.ValidCodeException;
import com.xxx.framework.security.token.CustomUsernamePasswordToken;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;


public class UserRealm extends AuthorizingRealm {
  private static Logger logger = Logger.getLogger(UserRealm.class);

  private UserDAO userDAO;

  public void setUserDAO(UserDAO userDAO) {
    this.userDAO = userDAO;
  }

  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    String username = (String) principals.getPrimaryPrincipal();

    SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
    authorizationInfo.setRoles(userDAO.getUserRoles(username));
    authorizationInfo.setStringPermissions(userDAO.findPermissions(username));

    return authorizationInfo;
  }

  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

    CustomUsernamePasswordToken login_token = (CustomUsernamePasswordToken) token;

    //校验码判断逻辑
    //取得用户输入的校验码
    String userInputValidCode = login_token.getValidCode();

    //取得真实的正确校验码
    String realRightValidCode = (String) SecurityUtils.getSubject().getSession().getAttribute("rand");

    if (null == userInputValidCode || !userInputValidCode.equalsIgnoreCase(realRightValidCode)) {
      logger.debug("验证码输入错误");
      throw new ValidCodeException("验证码输入不正确");
    }

    //以上校验码验证通过以后,查数据库
    String username = (String) token.getPrincipal();
    SysUserEntity user = userDAO.findByUsername(username);

    if (user == null) {
      throw new UnknownAccountException();//没找到帐号
    }

    if (Boolean.FALSE.equals(user.getValid())) {
      throw new LockedAccountException(); //帐号锁定
    }

    //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以自定义实现
    SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
        user.getLoginName(), //用户名
        user.getLoginPass(), //密码
        getName()  //realm name
    );
    return authenticationInfo;
  }

  @Override
  public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
    super.clearCachedAuthorizationInfo(principals);
  }

  @Override
  public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
    super.clearCachedAuthenticationInfo(principals);
  }

  @Override
  public void clearCache(PrincipalCollection principals) {
    super.clearCache(principals);
  }

  public void clearAllCachedAuthorizationInfo() {
    getAuthorizationCache().clear();
  }

  public void clearAllCachedAuthenticationInfo() {
    getAuthenticationCache().clear();
  }

  public void clearAllCache() {
    clearAllCachedAuthenticationInfo();
    clearAllCachedAuthorizationInfo();
  }

}

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

package com.xxx.framework.security.exception;

import org.apache.shiro.authc.AuthenticationException;

/**
 * Created on 2014/11/11.
 */
public class ValidCodeException extends AuthenticationException {

    public ValidCodeException(String msg){
        super(msg);
    }
}

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

package com.xxx.framework.security.dao;

import com.xxx.entity.SysUserEntity;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Created on 2014/11/10.
 */
public class UserDAO {

  private JdbcTemplate jt;

  public void setJt(JdbcTemplate jt) {
    this.jt = jt;
  }

  public Set<String> getUserRoles(String loginName) {
    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";
    return new HashSet(jt.queryForList(sql, String.class, loginName));
  }

  public Set<String> findPermissions(String loginName) {
    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";
    return new HashSet(jt.queryForList(sql, String.class, loginName));
  }

  public SysUserEntity findByUsername(String loginName) {
    String sql = "select id, user_code,login_name, login_pass, valid from sys_user where login_name=?";
    List<SysUserEntity> userList = jt.query(sql, new BeanPropertyRowMapper(SysUserEntity.class), loginName);
    if (userList.size() == 0) {
      return null;
    }
    return userList.get(0);
  }
}

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

package com.xxx.framework.security.credentials;

import com.xxx.framework.security.PasswordHelper;
import com.xxx.framework.security.token.CustomUsernamePasswordToken;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;

import java.util.concurrent.atomic.AtomicInteger;

public class RetryLimitSimpleCredentialsMatcher extends SimpleCredentialsMatcher {

  private Cache<String, AtomicInteger> passwordRetryCache;

  private PasswordHelper passwordHelper;

  public RetryLimitSimpleCredentialsMatcher(CacheManager cacheManager) {
    passwordRetryCache = cacheManager.getCache("passwordRetryCache");
  }

  public void setPasswordHelper(PasswordHelper passwordHelper) {
    this.passwordHelper = passwordHelper;
  }

  @Override
  public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
    CustomUsernamePasswordToken login_token = (CustomUsernamePasswordToken) token;

    String username = (String) token.getPrincipal();
    //retry count + 1
    AtomicInteger retryCount = passwordRetryCache.get(username);
    if (retryCount == null) {
      retryCount = new AtomicInteger(0);
      passwordRetryCache.put(username, retryCount);
    }
    if (retryCount.incrementAndGet() > 5) {
      //if retry count > 5 throw
      throw new ExcessiveAttemptsException();
    }


    String user_input_login_pass = passwordHelper.encryptPassword(login_token.getUsername(), String.valueOf(login_token.getPassword()));
    Object db_login_password = getCredentials(info);
    //将密码加密与系统加密后的密码校验,内容一致就返回true,不一致就返回false
    boolean matches = super.equals(user_input_login_pass, db_login_password);

    if (matches) {
      //clear retry count
      passwordRetryCache.remove(username);
    }
    return matches;
  }
}

用户信息实体类

package com.xxx.entity;

import javax.persistence.*;
import java.util.List;

/**
 * Created on 2014/11/7.
 * 系统用户信息
 */
@Entity
@Table(name = "sys_user")
public class SysUserEntity {

  @GeneratedValue(strategy =GenerationType.IDENTITY)
  @Column(name = "id",insertable = false,updatable = false)
  private Integer id;

  @Id
  @Column(name = "user_code",length = 6)
  private String userCode;

  @Column(name = "login_name",length = 40,nullable = false,unique = true)
  private String loginName;

  @Column(name = "login_pass",length = 50)
  private String loginPass;

  @Column(name = "address",length = 200)
  private String address;

  @Column(name = "telphone",length = 30)
  private String telPhone;

  @Column(name = "qq",length = 15)
  private String qq;

  @Column(name = "email",length = 40)
  private String email;

  @Column(name = "mobile",length = 30)
  private String mobile;

  @Column(name = "sort_id")
  private Short sortId;

  @Column(name = "valid")
  private Boolean valid;

  @ManyToMany(fetch = FetchType.LAZY)
  @JoinTable(name="sys_user_to_role",joinColumns = { @JoinColumn(name = "user_code") }, inverseJoinColumns = { @JoinColumn(name = "role_code")})
  private List<SysRoleEntity> roleList;

  public Integer getId() {
    return id;
  }

  public void setId(Integer id) {
    this.id = id;
  }

  public String getUserCode() {
    return userCode;
  }

  public void setUserCode(String userCode) {
    this.userCode = userCode;
  }

  public String getLoginName() {
    return loginName;
  }

  public void setLoginName(String loginName) {
    this.loginName = loginName;
  }

  public String getLoginPass() {
    return loginPass;
  }

  public void setLoginPass(String loginPass) {
    this.loginPass = loginPass;
  }

  public String getAddress() {
    return address;
  }

  public void setAddress(String address) {
    this.address = address;
  }

  public String getTelPhone() {
    return telPhone;
  }

  public void setTelPhone(String telPhone) {
    this.telPhone = telPhone;
  }

  public String getQq() {
    return qq;
  }

  public void setQq(String qq) {
    this.qq = qq;
  }

  public String getEmail() {
    return email;
  }

  public void setEmail(String email) {
    this.email = email;
  }

  public String getMobile() {
    return mobile;
  }

  public void setMobile(String mobile) {
    this.mobile = mobile;
  }

  public Short getSortId() {
    return sortId;
  }

  public void setSortId(Short sortId) {
    this.sortId = sortId;
  }

  public Boolean getValid() {
    return valid;
  }

  public void setValid(Boolean valid) {
    this.valid = valid;
  }

  public List<SysRoleEntity> getRoleList() {
    return roleList;
  }

  public void setRoleList(List<SysRoleEntity> roleList) {
    this.roleList = roleList;
  }

}

还有一个md5工具类

package com.xxx.framework.security;

import java.security.MessageDigest;

public class PasswordHelper {


  /**
   * 根据用户名与密码做md5单向hash加密
   *
   * @param username 用户名
   * @param password 用户密码明文
   * @return md5(username+password)
   */

  public String encryptPassword(String username, String password) {

    String inStr = username + password;

    MessageDigest md5 = null;
    try {
      md5 = MessageDigest.getInstance("MD5");
    } catch (Exception e) {
      System.out.println(e.toString());
      e.printStackTrace();
      return "";
    }
    char[] charArray = inStr.toCharArray();
    byte[] byteArray = new byte[charArray.length];

    for (int i = 0; i < charArray.length; i++)
      byteArray[i] = (byte) charArray[i];
    byte[] md5Bytes = md5.digest(byteArray);
    StringBuffer hexValue = new StringBuffer();
    for (int i = 0; i < md5Bytes.length; i++) {
      int val = ((int) md5Bytes[i]) & 0xff;
      if (val < 16)
        hexValue.append("0");
      hexValue.append(Integer.toHexString(val));
    }
    return hexValue.toString();

  }
}

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

package com.xxx.web.login;

import com.xxx.entity.SysUserEntity;
import com.xxx.framework.dao.BaseDAO;
import com.xxx.framework.security.PasswordHelper;
import com.xxx.framework.security.exception.ValidCodeException;
import com.xxx.framework.security.token.CustomUsernamePasswordToken;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping(value = "/login")
public class LoginController {

  private static final Logger logger = Logger.getLogger(LoginController.class);

  @Resource
  private BaseDAO<SysUserEntity> sys_user_dao;

  @RequestMapping(value = "/", method = RequestMethod.GET)
  public String login() {
    return "/login/login";
  }

  @RequestMapping(value = "/checklogin", method = RequestMethod.POST)
  @ResponseBody
  public Map<String, Object> checkLogin(SysUserEntity login_user,HttpServletRequest request,@RequestParam("validCode")String validCode) {
    Map<String, Object> result = new HashMap<String, Object>();
    result.put("msg", "用户名或者密码错误!");
    result.put("success", "true");
    result.put("status", false);

    boolean rememberMe = WebUtils.isTrue(request, FormAuthenticationFilter.DEFAULT_REMEMBER_ME_PARAM);
    String host = request.getRemoteHost();

    //构造登陆令牌环
    CustomUsernamePasswordToken token = new CustomUsernamePasswordToken(login_user.getLoginName(), login_user.getLoginPass().toCharArray(), rememberMe,host,validCode);

    try{
      //发出登陆请求
      SecurityUtils.getSubject().login(token);
      //登陆成功
      HttpSession session = request.getSession(true);
      try {
        SysUserEntity user = sys_user_dao.findOneEntityByHql("from SysUserEntity where loginName=?", login_user.getLoginName());
        if (null != user) {
          //根据输入的用户名和密码确实查到了用户信息
          session.removeAttribute("rand");
          session.setAttribute("current_login_user", user);
          result.put("msg", "登录成功!");
          result.put("status", true);
          result.put("main_url", "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/main");
        }
      } catch (Exception e) {
        logger.error(e.getMessage(), e);
      }
      return  result;
    }catch (UnknownAccountException e){
      result.put("msg", "账号不存在!");
    }catch (IncorrectCredentialsException e){
      result.put("msg", "用户名/密码错误!");
    }catch (ExcessiveAttemptsException e) {
      result.put("msg", "账户错误次数过多,暂时禁止登录!");
    }catch (ValidCodeException e){
      result.put("msg", "验证码输入错误!");
    }catch (Exception e){
      result.put("msg", "未知错误!");
    }
    return result;
  }

  @RequestMapping(value="/logout")
  public String logout(){
    Subject currentUser = SecurityUtils.getSubject();
    if (SecurityUtils.getSubject().getSession() != null)
    {
      currentUser.logout();
    }
    return "redirect:/login/";
  }

  @Resource
  private PasswordHelper passwordHelper;

  @RequestMapping(value = "/fuck")
  @ResponseBody
  public Map<String, Object> fuck() {
    Map<String, Object> result = new HashMap<String, Object>();
    result.put("success", "true");

    SysUserEntity user = sys_user_dao.findById(SysUserEntity.class, "0001");
    user.setLoginPass("a");
    String new_pass = passwordHelper.encryptPassword(user.getLoginName(), user.getLoginPass());
    user.setLoginPass(new_pass);

    sys_user_dao.update(user);

    return result;
  }

}

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值