@Override
public int saveObject(SysUser entity, Integer[] roleIds) {
// 1.參數(shù)合法驗(yàn)證
if (entity == null)
throw new IllegalArgumentException("保存對應(yīng)不能為空");
if (StringUtils.isEmpty(entity.getUsername()))
throw new ServiceException("用戶名不能為空");
if (StringUtils.isEmpty(entity.getPassword()))
throw new ServiceException("密碼不能為空");
if (roleIds == null || roleIds.length == 0)
throw new IllegalArgumentException("必須為用戶分配角色");
// 2.保存數(shù)據(jù)
// 2.1 創(chuàng)建一個鹽值(用于輔助加密,保證密碼更加安全的一種手段)
String salt = UUID.randomUUID().toString();
System.out.println(salt);
String pwd = entity.getPassword();
// 2.3 對密碼進(jìn)行加密,加密算法md5
SimpleHash sh = // 這個api屬于shiro框架,后續(xù)需要引入shiro依賴
new SimpleHash("MD5", // algorithmName 表示加密算法
pwd, // source 為要加密的對象
salt);// salt 加密鹽值
entity.setPassword(sh.toHex());
System.out.println(salt);
entity.setSalt(salt);
// 2.4設(shè)置對象其它屬性默認(rèn)值
entity.setCreatedTime(new Date());
entity.setModifiedTime(new Date());
// 2.5保存用戶自身信息
int rows = sysUserDao.insertObject(entity);
// 2.6保存用戶與角色的關(guān)系數(shù)據(jù)
sysUserRoleDao.insertObjects(entity.getId(), roleIds);
// 3.返回結(jié)果
return rows;
}
方案一:只處理一種異常昧诱,其他異常拋出
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("==doGetAuthenticationInfo===");
// 獲取用戶身份信息(如用戶名)
String userName = (String) token.getPrincipal();
// 1.從token對象獲取用戶名(用戶輸入的)
// 基于用戶名訪問數(shù)據(jù)庫獲取用戶信息
SysUser user = sysUserDao.findUserByUserName(userName);
// 對用戶信息進(jìn)行驗(yàn)證
// 2.基于用戶名查詢用戶信息并進(jìn)行身份校驗(yàn)
if (user == null)// 驗(yàn)證用戶名是否為空
throw new AuthenticationException("此用戶不存在");
if (user.getValid() == 0)// 驗(yàn)證用戶是否被禁用
throw new AuthenticationException("此用戶已被禁用");
// 3.對用戶信息進(jìn)行封裝(基于業(yè)務(wù)封裝用戶數(shù)據(jù))
ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt());
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, // principal
// 用戶->身份
user.getPassword(), // hashedCredentials已加密的憑證
credentialsSalt, // credentialsSalt 密碼加密時使用的鹽
this.getName());// realmName 當(dāng)前方法所在類的名字
return info;// 返回給誰?認(rèn)證管理器
}
@ExceptionHandler(IncorrectCredentialsException.class)
@ResponseBody
public JsonResult doHandleShiroException(IncorrectCredentialsException e){
JsonResult result=new JsonResult();
result.setState(0);
result.setMessage("密碼不正確");
return result;
}
方案二:處理多種異常心褐,ShiroException作為異常的父類
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("==doGetAuthenticationInfo===");
// 獲取用戶身份信息(如用戶名)
String userName = (String) token.getPrincipal();
// 1.從token對象獲取用戶名(用戶輸入的)
// 基于用戶名訪問數(shù)據(jù)庫獲取用戶信息
SysUser user = sysUserDao.findUserByUserName(userName);
// 對用戶信息進(jìn)行驗(yàn)證
// 2.基于用戶名查詢用戶信息并進(jìn)行身份校驗(yàn)
if (user == null)// 驗(yàn)證用戶名是否為空
throw new UnknownAccountException();
if (user.getValid() == 0)// 驗(yàn)證用戶是否被禁用
throw new LockedAccountException();
// 3.對用戶信息進(jìn)行封裝(基于業(yè)務(wù)封裝用戶數(shù)據(jù))
ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt());
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, // principal
// 用戶->身份
user.getPassword(), // hashedCredentials已加密的憑證
credentialsSalt, // credentialsSalt 密碼加密時使用的鹽
this.getName());// realmName 當(dāng)前方法所在類的名字
return info;// 返回給誰?認(rèn)證管理器
}
@ExceptionHandler(ShiroException.class)
@ResponseBody
public JsonResult doHandleShiroException(ShiroException e){
JsonResult result=new JsonResult();
result.setState(0);
if(e instanceof IncorrectCredentialsException)
result.setMessage("密碼不正確");
else if(e instanceof UnknownAccountException)
result.setMessage("此賬戶不存在");
else if(e instanceof LockedAccountException)
result.setMessage("賬戶已被禁用");
return result;
}
方案二:完整代碼
package com.jt.service.realm;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.jt.dao.SysUserDao;
import com.jt.entity.SysUser;
/**
* 此對象中要完成用戶認(rèn)證信息,授權(quán)信息的獲取和封裝等業(yè)務(wù)操作
*
* @author Administrator
*
*/
@Service
public class ShiroUserRealm extends AuthorizingRealm {
@Autowired
private SysUserDao sysUserDao;
/**
* 設(shè)置憑證(Credentials)匹配器
* 指定加密算法和加密次數(shù)榛做,默認(rèn)加密一次
*/
@Override
public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
HashedCredentialsMatcher cMatcher = new HashedCredentialsMatcher("MD5");
// 設(shè)置加密的次數(shù)(這個次數(shù)應(yīng)該與保存密碼時那個加密次數(shù)一致)
// cMatcher.setHashIterations(5);
super.setCredentialsMatcher(cMatcher);
}
/**
* 負(fù)責(zé)用戶認(rèn)證信息的獲取及封裝
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("==doGetAuthenticationInfo===");
// 獲取用戶身份信息(如用戶名)
String userName = (String) token.getPrincipal();
// 1.從token對象獲取用戶名(用戶輸入的)
// 基于用戶名訪問數(shù)據(jù)庫獲取用戶信息
SysUser user = sysUserDao.findUserByUserName(userName);
// 對用戶信息進(jìn)行驗(yàn)證
// 2.基于用戶名查詢用戶信息并進(jìn)行身份校驗(yàn)
if (user == null)// 驗(yàn)證用戶名是否為空
throw new UnknownAccountException();
if (user.getValid() == 0)// 驗(yàn)證用戶是否被禁用
throw new LockedAccountException();
// 3.對用戶信息進(jìn)行封裝(基于業(yè)務(wù)封裝用戶數(shù)據(jù))
ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt());
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, // principal
// 用戶->身份
user.getPassword(), // hashedCredentials已加密的憑證
credentialsSalt, // credentialsSalt 密碼加密時使用的鹽
this.getName());// realmName 當(dāng)前方法所在類的名字
return info;// 返回給誰?認(rèn)證管理器
}
/**
* 負(fù)責(zé)用戶授權(quán)信息的獲取及封裝
* */
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
return null;
}
}
package com.jt.common.web;
import java.util.logging.Logger;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import com.jt.common.vo.JsonResult;
@ControllerAdvice
public class GlobalExceptionHandler {
/**
* 處理運(yùn)行時異常
* @return
*/
//jdk中自帶的日志api
private Logger log=Logger.getLogger(GlobalExceptionHandler.class.getName());
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public JsonResult doHandleRuntimeException(RuntimeException e){
/**
* 封裝異常信息
*/
//e.printStackTrace();
log.info(e.getMessage());
return new JsonResult(e);
}
@ExceptionHandler(ShiroException.class)
@ResponseBody
public JsonResult doHandleShiroException(ShiroException e){
JsonResult result=new JsonResult();
result.setState(0);
if(e instanceof IncorrectCredentialsException)
result.setMessage("密碼不正確");
else if(e instanceof UnknownAccountException)
result.setMessage("此賬戶不存在");
else if(e instanceof LockedAccountException)
result.setMessage("賬戶已被禁用");
return result;
}
}
package com.jt.dao;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.jt.common.vo.SysUserDeptResult;
import com.jt.entity.SysUser;
public interface SysUserDao {
/**
* 更新用戶信息
* @param entity
* @return
*/
int updateObject(SysUser entity);
/**
* 根據(jù)用戶id查詢用戶以及用戶對應(yīng)的部門信息
* @param id (用戶id)
* @return
*/
SysUserDeptResult findObjectById(Integer id);
/**
*
* @param deptId 部門id
* @return
*/
int getUserCountByDeptId(Integer deptId);
/**
* 根據(jù)用戶名查找用戶信息
* @param username
* @return
*/
SysUser findUserByUserName(String username);
/**
* 負(fù)責(zé)將用戶信息寫入到數(shù)據(jù)庫
* @param entity
* @return
*/
int insertObject(SysUser entity);
/**
* 賦值執(zhí)行禁用和啟用操作
* @param id 要禁用或啟用的記錄id
* @param valid 禁用或啟用的標(biāo)識
* @return
*/
int validById(@Param("id")Integer id,
@Param("valid")Integer valid,
@Param("modifiedUser") String modifiedUser);
/**
* 依據(jù)條件分頁查詢操作
* @param username
* @param startIndex
* @param pageSize
* @return
*/
List<SysUserDeptResult> findPageObjects(
@Param("username")String username,
@Param("startIndex")Integer startIndex,
@Param("pageSize")Integer pageSize);
/**
* 依據(jù)條件統(tǒng)計記錄總數(shù)
* @param username
* @return
*/
int getRowCount(@Param("username")String username);
}
<select id="findUserByUserName" resultType="com.jt.entity.SysUser">
select *
from sys_users
where username=#{username}
</select>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jt.dao.SysUserDao">
<!-- 更新用戶自身信息 -->
<update id="updateObject" parameterType="com.jt.entity.SysUser">
update sys_users
<set>
<if test="username!=null and username!=''">
username=#{username},
</if>
<if test="email!=null and email!=''">
email=#{email},
</if>
<if test="mobile!=null and mobile!=''">
mobile=#{mobile},
</if>
<if test="deptId!=null and deptId!=''">
deptId=#{deptId},
</if>
<if test="modifiedUser!=null and modifiedUser!=''">
modifiedUser=#{modifiedUser},
</if>
modifiedTime=now()
</set>
where id=#{id}
</update>
<select id="findObjectById" resultMap="sysUserResult">
select *
from sys_users
where id=#{id}
</select>
<!-- 基于用戶名查詢當(dāng)前用戶對象 -->
<select id="findUserByUserName" resultType="com.jt.entity.SysUser">
select *
from sys_users
where username=#{username}
</select>
<insert id="insertObject" parameterType="com.jt.entity.SysUser"
useGeneratedKeys="true" keyProperty="id">
insert into sys_users
(username,password,salt,email,mobile,valid,deptId,
createdTime,modifiedTime,createdUser,modifiedUser)
values
(#{username},#{password},#{salt},
#{email},#{mobile},#{valid},#{deptId},
now(),now(),#{createdUser},#{modifiedUser}
)
</insert>
<!-- 禁用或啟用用戶對象 -->
<update id="validById">
update sys_users
set
valid=#{valid},
modifiedTime=now(),
modifiedUser=#{modifiedUser}
where id=#{id}
</update>
<resultMap id="sysUserResult" type="com.jt.common.vo.SysUserDeptResult">
<!--直接量類型的屬性自動映射-->
<!--關(guān)聯(lián)映射-->
<association property="sysDept" column="deptId"
select="com.jt.dao.SysDeptDao.findById" />
</resultMap>
<select id="getUserCountByDeptId" resultType="int">
select count(*)
from sys_users
where deptId=#{deptId}
</select>
<sql id="queryWhereId">
<where>
<if test="username!=null and username!=''">
username like concat("%",#{username},"%")
</if>
</where>
</sql>
<select id="findPageObjects" resultMap="sysUserResult">
select *
from sys_users
<include refid="queryWhereId" />
limit #{startIndex},#{pageSize}
</select>
<select id="getRowCount" resultType="int">
select count(*)
from sys_users
<include refid="queryWhereId" />
</select>
</mapper>