This commit is contained in:
xiangwb
2018-03-28 16:47:51 +08:00
parent a7ce1046c3
commit 80d3386cd3
7 changed files with 284 additions and 17 deletions
@@ -417,7 +417,7 @@ public class SysUserService {
* @param userName
* @return
*/
private SysUser getByUserName(String userName) {
public SysUser getByUserName(String userName) {
return sysUserRepository.getByUserName(userName);
}
@@ -429,15 +429,26 @@ public class SysUserService {
* @param salt
* @return
*/
private boolean checkPassWord(String passWord, String realPassWord, String salt) {
public boolean checkPassWord(String passWord, String realPassWord, String salt) {
String validatePassWord = getSysPassWord(passWord, salt);
//判断密码是否相同
return realPassWord.equals(validatePassWord);
}
/**
* 获取数据库密码
*
* @param passWord
* @param salt
* @return
*/
public String getSysPassWord(String passWord, String salt) {
// 根据密码盐值 解码
byte[] saltByte = EncodeUtils.hexDecode(salt);
byte[] hashPassword = Digests.sha1(passWord.getBytes(), saltByte,
PassWordUtil.HASH_INTERATIONS);
// 密码 数据库中密码
String validatePassWord = EncodeUtils.hexEncode(hashPassword);
//判断密码是否相同
return realPassWord.equals(validatePassWord);
return EncodeUtils.hexEncode(hashPassword);
}
/**
@@ -0,0 +1,23 @@
package com.xwbing.util.captcha;
/**
* 项目名称: boot-module-demo
* 创建时间: 2018/3/28 14:51
* 作者: xiangwb
* 说明:
*/
public class CaptchaException extends RuntimeException {
private static final long serialVersionUID = 3106485920407116428L;
public CaptchaException(Throwable cause) {
super(cause);
}
public CaptchaException(String message) {
super(message);
}
public CaptchaException(String message, Throwable cause) {
super(message, cause);
}
}
@@ -4,16 +4,13 @@ import com.alibaba.fastjson.JSONObject;
import com.xwbing.annotation.LogInfo;
import com.xwbing.constant.CommonConstant;
import com.xwbing.constant.CommonEnum;
import com.xwbing.domain.entity.sys.SysAuthority;
import com.xwbing.domain.entity.sys.SysRole;
import com.xwbing.domain.entity.sys.SysUser;
import com.xwbing.domain.entity.sys.SysUserRole;
import com.xwbing.domain.entity.sys.*;
import com.xwbing.domain.entity.vo.*;
import com.xwbing.service.sys.SysAuthorityService;
import com.xwbing.service.sys.SysRoleService;
import com.xwbing.service.sys.SysUserRoleService;
import com.xwbing.service.sys.SysUserService;
import com.xwbing.redis.RedisService;
import com.xwbing.service.sys.*;
import com.xwbing.shiro.UsernamePasswordCaptchaToken;
import com.xwbing.util.CommonDataUtil;
import com.xwbing.util.IpUtil;
import com.xwbing.util.JsonResult;
import com.xwbing.util.RestMessage;
import io.swagger.annotations.Api;
@@ -21,6 +18,8 @@ import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@@ -28,6 +27,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
@@ -48,6 +48,10 @@ public class SysUserControl {
private SysRoleService sysRoleService;
@Resource
private SysAuthorityService sysAuthorityService;
@Resource
private RedisService redisService;
@Resource
private SysUserLoginInOutService loginInOutService;
@LogInfo("添加用户")
@ApiOperation(value = "添加用户", response = RestMessageVo.class)
@@ -115,6 +119,36 @@ public class SysUserControl {
return JsonResult.toJSONObj(login);
}
@LogInfo("登录")
@ApiOperation(value = "登录", response = RestMessageVo.class)
@PostMapping("login2")
public JSONObject login2(HttpServletRequest request, @RequestParam String userName, @RequestParam String passWord, @RequestParam String checkCode, boolean rememberMe) {
if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(passWord)) {
return JsonResult.toJSONObj("用户名或密码不能为空");
}
if (StringUtils.isEmpty(checkCode)) {
return JsonResult.toJSONObj("请输入验证码");
}
SysUser user = sysUserService.getByUserName(userName);
Subject subject = SecurityUtils.getSubject();
String ip = IpUtil.getIpAddr(request);
UsernamePasswordCaptchaToken token = new UsernamePasswordCaptchaToken(userName, passWord.toCharArray(), rememberMe, ip, checkCode);
subject.login(token);
if (subject.isAuthenticated()) {
//保存登录信息
SysUserLoginInOut loginInOut = new SysUserLoginInOut();
loginInOut.setCreateTime(new Date());
loginInOut.setUserId(user.getId());
loginInOut.setInoutType(CommonEnum.LoginInOutEnum.IN.getValue());
loginInOut.setIp(ip);
RestMessage save = loginInOutService.save(loginInOut);
if (!save.isSuccess()) {
return JsonResult.toJSONObj("保存用户登录日志失败");
}
}
return JsonResult.toJSONObj(new Object(), "登录成功");
}
@LogInfo("登出")
@ApiOperation(value = "登出", response = RestMessageVo.class)
@GetMapping("logout")
@@ -123,6 +157,28 @@ public class SysUserControl {
return JsonResult.toJSONObj(logout);
}
@LogInfo("登出")
@ApiOperation(value = "登出", response = RestMessageVo.class)
@GetMapping("logout2")
public JSONObject logout2(HttpServletRequest request) {
Subject subject = SecurityUtils.getSubject();
if (subject != null && subject.getPrincipals() != null) {
SysUser sysUser = (SysUser) subject.getPrincipals().getPrimaryPrincipal();
if (null != sysUser) {
SysUserLoginInOut loginInOut = new SysUserLoginInOut();
loginInOut.setCreateTime(new Date());
loginInOut.setUserId(sysUser.getId());
loginInOut.setInoutType(CommonEnum.LoginInOutEnum.OUT.getValue());
loginInOut.setIp(IpUtil.getIpAddr(request));
RestMessage out = loginInOutService.save(loginInOut);
if (out.isSuccess()) {
return JsonResult.toJSONObj("保存用户登出信息失败");
}
}
}
return JsonResult.toJSONObj(new Object(),"登出成功");
}
@LogInfo("修改密码")
@ApiOperation(value = "修改密码", response = RestMessageVo.class)
@PostMapping("updatePassWord")
@@ -0,0 +1,103 @@
package com.xwbing.shiro;
import com.xwbing.constant.CommonConstant;
import com.xwbing.domain.entity.sys.SysAuthority;
import com.xwbing.domain.entity.sys.SysRole;
import com.xwbing.domain.entity.sys.SysUser;
import com.xwbing.exception.BusinessException;
import com.xwbing.service.sys.SysRoleService;
import com.xwbing.service.sys.SysUserService;
import com.xwbing.util.captcha.CaptchaException;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 项目名称: boot-module-demo
* 创建时间: 2018/3/28 14:32
* 作者: xiangwb
* 说明:
*/
@Component
public class MyShiroRealm extends AuthorizingRealm {
@Resource
private SysUserService sysUserService;
@Resource
private SysRoleService sysRoleService;
/**
* 授权
*
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// 获取验证的对象
if (principalCollection == null) {
throw new AuthorizationException("Principal对象不能为空");
}
SysUser user = (SysUser) principalCollection.fromRealm(getName()).iterator().next();
if (user != null) {
// 权限信息对象info,用来存放查出的用户的所有的角色(role)及权限(permission)
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 用户的角色集合
List<SysRole> sysRoles = sysRoleService.listByUserIdEnable(user.getId(), "Y");
Set<String> roles = new HashSet<>();
sysRoles.forEach(sysRole -> roles.add(sysRole.getName()));
info.setRoles(roles);
//用户的权限集合
Set<String> permissions = new HashSet<>();
List<SysAuthority> sysAuthorities = sysUserService.listAuthorityByIdAndEnable(user.getId(), "Y");
sysAuthorities.forEach(sysAuthority -> permissions.add(sysAuthority.getUrl()));
info.setStringPermissions(permissions);
return info;
}
return null;
}
/**
* 验证用户身份
*
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordCaptchaToken captchaToken = (UsernamePasswordCaptchaToken) authenticationToken;
SysUser user = sysUserService.getByUserName(captchaToken.getUsername());
if (user == null) {
throw new BusinessException("账号错误");
}
String sysPassWord = user.getPassword();
String salt = user.getSalt();
boolean flag = sysUserService.checkPassWord(String.valueOf(captchaToken.getPassword()), sysPassWord, salt);
if (!flag) {
throw new BusinessException("密码错误");
}
String captcha = captchaToken.getCaptcha();
String exitCode = (String) SecurityUtils.getSubject().getSession()
.getAttribute(CommonConstant.KEY_CAPTCHA);
if (StringUtils.isEmpty(captcha) || !captcha.equalsIgnoreCase(exitCode)) {
throw new CaptchaException("验证码错误");
}
return new SimpleAuthenticationInfo(user, sysPassWord,
ByteSource.Util.bytes(salt), getName());
}
}
@@ -0,0 +1,58 @@
package com.xwbing.shiro;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 项目名称: boot-module-demo
* 创建时间: 2018/3/28 14:06
* 作者: xiangwb
* 说明:
*/
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/login");
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/index");
// 未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
// 拦截器.
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// 配置不会被拦截的链接 顺序判断
filterChainDefinitionMap.put("/static/**", "anon");
filterChainDefinitionMap.put("/ajaxLogin", "anon");
// 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/add", "perms[权限添加]");
// <!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
// <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
System.out.println("Shiro拦截器工厂类注入成功");
return shiroFilterFactoryBean;
}
@Bean
public MyShiroRealm shiroRealm() {
return new MyShiroRealm();
}
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(shiroRealm());
return securityManager;
}
}
@@ -0,0 +1,12 @@
package com.xwbing.shiro;
import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
/**
* 项目名称: boot-module-demo
* 创建时间: 2018/3/28 16:42
* 作者: xiangwb
* 说明:
*/
public class UrlPermissionsFilter extends PermissionsAuthorizationFilter {
}
@@ -1,17 +1,21 @@
package com.xwbing.shiro;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.shiro.authc.UsernamePasswordToken;
/**
* 项目名称: boot-module-demo
* 创建时间: 2018/3/28 14:44
* 作者: xiangwb
* 说明: :扩展默认的用户认证的bean
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class UsernamePasswordCaptchaToken extends UsernamePasswordToken {
private static final long serialVersionUID = 6059396037971862504L;
private String captcha;
public UsernamePasswordCaptchaToken() {
super();
}
public UsernamePasswordCaptchaToken(String username, char[] password, boolean rememberMe, String host, String captcha) {
super(username, password, rememberMe, host);
this.captcha = captcha;