merge
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user