异常信息拦截

v1.4.1
Parker 4 years ago
parent 29919cadc3
commit 386e692957

@ -0,0 +1,21 @@
package org.opsli.common.exception;
import org.opsli.common.base.msg.BaseMsg;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.plugins.mail.exception
* @Author: Parker
* @CreateTime: 2020-09-14 18:44
* @Description: Jwt
*/
public class JwtException extends ServiceException {
public JwtException(Integer code, String errorMessage) {
super(code, errorMessage);
}
public JwtException(BaseMsg msg) {
super(msg);
}
}

@ -0,0 +1,21 @@
package org.opsli.common.exception;
import org.opsli.common.base.msg.BaseMsg;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.plugins.mail.exception
* @Author: Parker
* @CreateTime: 2020-09-14 18:44
* @Description:
*/
public class TokenException extends ServiceException {
public TokenException(Integer code, String errorMessage) {
super(code, errorMessage);
}
public TokenException(BaseMsg msg) {
super(msg);
}
}

@ -1,38 +0,0 @@
package org.opsli.core.filter;
import org.apache.commons.lang3.StringUtils;
import org.opsli.common.api.TokenThreadLocal;
import org.opsli.core.utils.UserTokenUtil;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* Token token
*/
public class TokenFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
// 获得请求中 Token
String requestToken = UserTokenUtil.getRequestToken(request);
if(StringUtils.isNotEmpty(requestToken)){
// 放入当前线程缓存中
TokenThreadLocal.put(requestToken);
}
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
// 线程销毁时 删除 token
TokenThreadLocal.remove();
}
}

@ -3,9 +3,13 @@ package org.opsli.core.handler;
import cn.hutool.core.text.StrFormatter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.opsli.api.base.result.ResultVo;
import org.opsli.common.exception.EmptyException;
import org.opsli.common.exception.JwtException;
import org.opsli.common.exception.ServiceException;
import org.opsli.common.exception.TokenException;
import org.opsli.core.msg.CoreMsg;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
@ -78,6 +82,51 @@ public class GlobalExceptionHandler {
return ResultVo.error(e.getCode(), e.getMessage());
}
/**
* Jwt
*/
@ExceptionHandler(JwtException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResultVo<?> jwtException(JwtException e) {
return ResultVo.error(e.getCode(), e.getMessage());
}
/**
* Shiro
*/
@ExceptionHandler(IncorrectCredentialsException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResultVo<?> incorrectCredentialsException(IncorrectCredentialsException e) {
// token失效请重新登录
return ResultVo.error(e.getMessage());
}
/**
* Shiro
*/
@ExceptionHandler(LockedAccountException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResultVo<?> lockedAccountException(LockedAccountException e) {
// 账号已被锁定,请联系管理员
return ResultVo.error(e.getMessage());
}
/**
* Token
*/
@ExceptionHandler(TokenException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResultVo<?> tokenException(LockedAccountException e) {
// Token 异常
return ResultVo.error(e.getMessage());
}
// ============================
/**
*
*/
@ -88,6 +137,7 @@ public class GlobalExceptionHandler {
return ResultVo.error(e.getCode(), e.getMessage());
}
/**
*
*/

@ -0,0 +1,38 @@
package org.opsli.core.msg;
import org.opsli.common.base.msg.BaseMsg;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.msg
* @Author: Parker
* @CreateTime: 2020-09-13 19:36
* @Description: -
*/
public enum JwtMsg implements BaseMsg {
EXCEPTION_TOKEN(11000,"认证解密异常: {}"),
EXCEPTION_DECODE(10101,"解密异常: {}"),
EXCEPTION_ENCODE(10102,"加密异常: {}"),
;
private int code;
private String message;
JwtMsg(int code, String message){
this.code = code;
this.message = message;
}
@Override
public Integer getCode() {
return this.code;
}
@Override
public String getMessage() {
return this.message;
}
}

@ -0,0 +1,54 @@
package org.opsli.core.msg;
import org.opsli.common.base.msg.BaseMsg;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.msg
* @Author: Parker
* @CreateTime: 2020-09-13 19:36
* @Description: Token -
*/
public enum TokenMsg implements BaseMsg {
/**
* Token
*/
EXCEPTION_TOKEN_CREATE_ERROR(12000,"生成Token失败"),
EXCEPTION_TOKEN_LOSE_EFFICACY(12001,"Token失效请重新登录"),
/**
*
*/
EXCEPTION_LOGIN_CAPTCHA(12100,"验证码不正确!"),
EXCEPTION_LOGIN_ACCOUNT_NO(12101,"账号或密码不正确!"),
EXCEPTION_LOGIN_ACCOUNT_LOCKED(12102,"账号已被锁定,请联系管理员!"),
EXCEPTION_LOGOUT_ERROR(12103,"登出失败没有授权Token"),
EXCEPTION_LOGOUT_SUCCESS(12104,"登出成功!"),
/**
*
*/
EXCEPTION_USER_NULL(12200, "用户为空"),
;
private int code;
private String message;
TokenMsg(int code, String message){
this.code = code;
this.message = message;
}
@Override
public Integer getCode() {
return this.code;
}
@Override
public String getMessage() {
return this.message;
}
}

@ -6,6 +6,7 @@ import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.opsli.api.wrapper.system.user.UserModel;
import org.opsli.core.msg.TokenMsg;
import org.opsli.core.security.shiro.token.OAuth2Token;
import org.opsli.core.utils.UserTokenUtil;
import org.opsli.core.utils.UserUtil;
@ -53,13 +54,17 @@ public class OAuth2Realm extends AuthorizingRealm {
* ()
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
throws AuthenticationException {
String accessToken = (String) token.getPrincipal();
// 1. 校验 token 是否有效
boolean verify = UserTokenUtil.verify(accessToken);
if(!verify){
throw new IncorrectCredentialsException("token失效请重新登录");
// token失效请重新登录
throw new IncorrectCredentialsException(
TokenMsg.EXCEPTION_TOKEN_LOSE_EFFICACY.getMessage());
}
// 2. 查询 用户信息
@ -68,7 +73,9 @@ public class OAuth2Realm extends AuthorizingRealm {
// 3. 校验账户是否锁定
if(user == null || user.getLocked().equals('1')){
throw new LockedAccountException("账号已被锁定,请联系管理员");
// 账号已被锁定,请联系管理员
throw new LockedAccountException(
TokenMsg.EXCEPTION_LOGIN_ACCOUNT_LOCKED.getMessage());
}
return new SimpleAuthenticationInfo(user, accessToken, getName());

@ -36,6 +36,7 @@ public class CaptchaUtil{
if(StringUtils.isBlank(uuid)){
throw new RuntimeException("uuid不能为空");
}
//生成文字验证码
String code = producer.createText();

@ -1,5 +1,6 @@
package org.opsli.core.utils;
import cn.hutool.core.util.StrUtil;
import cn.hutool.setting.dialect.Props;
import cn.hutool.setting.dialect.PropsUtil;
import com.auth0.jwt.JWT;
@ -9,6 +10,8 @@ import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.opsli.common.constants.SignConstants;
import org.opsli.common.exception.JwtException;
import org.opsli.core.msg.JwtMsg;
import java.io.UnsupportedEncodingException;
import java.util.Date;
@ -52,7 +55,9 @@ public final class JwtUtil {
verifier.verify(token);
return true;
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("认证解密异常:" + e.getMessage());
// 认证解密异常
String msg = StrUtil.format(JwtMsg.EXCEPTION_TOKEN.getMessage(), e.getMessage());
throw new JwtException(JwtMsg.EXCEPTION_TOKEN.getCode(), msg);
}
}
@ -67,7 +72,9 @@ public final class JwtUtil {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim(claim).asString();
} catch (JWTDecodeException e) {
throw new RuntimeException("解密异常:" + e.getMessage());
// 解密异常
String msg = StrUtil.format(JwtMsg.EXCEPTION_DECODE.getMessage(), e.getMessage());
throw new JwtException(JwtMsg.EXCEPTION_DECODE.getCode(), msg);
}
}
@ -92,7 +99,9 @@ public final class JwtUtil {
.withExpiresAt(date)
.sign(algorithm);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("加密异常:" + e.getMessage());
// 加密异常
String msg = StrUtil.format(JwtMsg.EXCEPTION_ENCODE.getMessage(), e.getMessage());
throw new JwtException(JwtMsg.EXCEPTION_ENCODE.getCode(), msg);
}
}

@ -1,6 +1,9 @@
package org.opsli.core.utils;
import org.opsli.common.exception.TokenException;
import org.opsli.core.msg.TokenMsg;
import java.security.MessageDigest;
import java.util.UUID;
@ -33,7 +36,8 @@ public final class TokenGenerator {
byte[] messageDigest = algorithm.digest();
return toHexString(messageDigest);
} catch (Exception e) {
throw new RuntimeException("生成Token失败", e);
// 生成Token失败
throw new TokenException(TokenMsg.EXCEPTION_TOKEN_CREATE_ERROR);
}
}

@ -10,6 +10,7 @@ import org.apache.shiro.crypto.hash.Md5Hash;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.wrapper.system.user.UserModel;
import org.opsli.common.constants.SignConstants;
import org.opsli.core.msg.TokenMsg;
import org.opsli.plugins.redis.RedisPlugin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -26,6 +27,8 @@ import java.util.Map;
@Component
public class UserTokenUtil {
/** token缓存名 */
private static final String TOKEN_NAME = "token";
/** 缓存前缀 */
private static final String PREFIX = "opsli:ticket:";
@ -40,7 +43,8 @@ public class UserTokenUtil {
*/
public static ResultVo<Map<String,Object>> createToken(UserModel user) {
if (user == null) {
return ResultVo.error("生成Token失败");
// 生成Token失败
return ResultVo.error(TokenMsg.EXCEPTION_TOKEN_CREATE_ERROR.getMessage());
}
Map<String,Object> map = Maps.newHashMapWithExpectedSize(2);
@ -73,7 +77,10 @@ public class UserTokenUtil {
map.put("expire", endTimestamp);
return ResultVo.success(map);
}
return ResultVo.error("生成Token失败");
// 生成Token失败
return ResultVo.error(TokenMsg.EXCEPTION_TOKEN_CREATE_ERROR.getMessage());
}catch (Exception e){
log.error(e.getMessage() , e);
return ResultVo.error(e.getMessage());
@ -165,11 +172,11 @@ public class UserTokenUtil {
*/
public static String getRequestToken(HttpServletRequest httpRequest){
//从header中获取token
String token = httpRequest.getHeader("token");
String token = httpRequest.getHeader(TOKEN_NAME);
//如果header中不存在token则从参数中获取token
if(StringUtils.isBlank(token)){
token = httpRequest.getParameter("token");
token = httpRequest.getParameter(TOKEN_NAME);
}
return token;

@ -9,7 +9,9 @@ import org.opsli.api.web.system.user.UserApi;
import org.opsli.api.wrapper.system.menu.MenuModel;
import org.opsli.api.wrapper.system.user.UserModel;
import org.opsli.common.api.TokenThreadLocal;
import org.opsli.common.exception.TokenException;
import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.msg.TokenMsg;
import org.opsli.plugins.redis.RedisLockPlugins;
import org.opsli.plugins.redis.lock.RedisLock;
import org.springframework.beans.factory.annotation.Autowired;
@ -60,7 +62,8 @@ public class UserUtil {
String userId = UserTokenUtil.getUserIdByToken(token);
UserModel user = getUser(userId);
if(user == null){
throw new RuntimeException("Token 失效");
// Token失效请重新登录
throw new TokenException(TokenMsg.EXCEPTION_TOKEN_LOSE_EFFICACY);
}
return user;
}
@ -481,7 +484,8 @@ public class UserUtil {
UserModel user = getUser();
if(user == null){
throw new RuntimeException("用户为空");
// 用户为空
throw new TokenException(TokenMsg.EXCEPTION_USER_NULL);
}
// 如果是超级管理员 则不进行租户处理

@ -21,12 +21,15 @@ public enum SystemMsg implements BaseMsg {
/**
*
*/
EXCEPTION_ROLE_UNIQUE(20000,"角色编号重复,该角色已存在!"),
EXCEPTION_ROLE_UNIQUE(20100,"角色编号重复,该角色已存在!"),
/**
*
*/
EXCEPTION_USER_UNIQUE(20000,"该用户已存在!"),
EXCEPTION_USER_UNIQUE(20200,"该用户已存在!"),
;

@ -8,9 +8,11 @@ import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.wrapper.system.user.UserModel;
import org.opsli.common.api.TokenThreadLocal;
import org.opsli.core.msg.TokenMsg;
import org.opsli.core.utils.CaptchaUtil;
import org.opsli.core.utils.UserTokenUtil;
import org.opsli.core.utils.UserUtil;
import org.opsli.modulars.system.SystemMsg;
import org.opsli.modulars.system.login.entity.LoginForm;
import org.springframework.web.bind.annotation.*;
@ -41,8 +43,9 @@ public class LoginRestController {
@PostMapping("/sys/login")
public ResultVo<?> login(@RequestBody LoginForm form){
boolean captcha = CaptchaUtil.validate(form.getUuid(), form.getCaptcha());
// 验证码不正确
if(!captcha){
return ResultVo.error("验证码不正确");
return ResultVo.error(TokenMsg.EXCEPTION_LOGIN_CAPTCHA.getMessage());
}
//用户信息
@ -51,12 +54,12 @@ public class LoginRestController {
//账号不存在、密码错误
if(user == null ||
!user.getPassword().equals(new Md5Hash(form.getPassword(), user.getSecretkey()).toHex())) {
return ResultVo.error("账号或密码不正确");
return ResultVo.error(TokenMsg.EXCEPTION_LOGIN_ACCOUNT_NO.getMessage());
}
//账号锁定
if(user.getLocked() == 1){
return ResultVo.error("账号已被锁定,请联系管理员");
return ResultVo.error(TokenMsg.EXCEPTION_LOGIN_ACCOUNT_LOCKED.getMessage());
}
//生成token并保存到Redis
@ -71,11 +74,12 @@ public class LoginRestController {
@PostMapping("/sys/logout")
public ResultVo<?> logout() {
String token = TokenThreadLocal.get();
// 登出失败没有授权Token
if(StringUtils.isEmpty(token)){
return ResultVo.success("登出失败没有授权Token");
return ResultVo.error(TokenMsg.EXCEPTION_LOGOUT_ERROR.getMessage());
}
UserTokenUtil.logout(token);
return ResultVo.success("登出成功!");
return ResultVo.success(TokenMsg.EXCEPTION_LOGOUT_SUCCESS.getMessage());
}
/**

@ -36,7 +36,7 @@ public class MenuRestController extends BaseRestController<SysMenu, MenuModel, I
* @param model
* @return ResultVo
*/
@ApiOperation(value = "获得单条字典明细数据", notes = "获得单条字典明细数据 - ID")
@ApiOperation(value = "获得单条菜单", notes = "获得单条菜单 - ID")
@Override
public ResultVo<MenuModel> get(MenuModel model) {
// 如果系统内部调用 则直接查数据库
@ -70,12 +70,12 @@ public class MenuRestController extends BaseRestController<SysMenu, MenuModel, I
* @param model
* @return ResultVo
*/
@ApiOperation(value = "新增字典明细数据", notes = "新增字典明细数据")
@ApiOperation(value = "新增菜单", notes = "新增菜单")
@Override
public ResultVo<?> insert(MenuModel model) {
// 调用新增方法
IService.insert(model);
return ResultVo.success("新增字典明细数据成功");
return ResultVo.success("新增菜单成功");
}
/**
@ -83,12 +83,12 @@ public class MenuRestController extends BaseRestController<SysMenu, MenuModel, I
* @param model
* @return ResultVo
*/
@ApiOperation(value = "修改字典明细数据", notes = "修改字典明细数据")
@ApiOperation(value = "修改菜单", notes = "修改菜单")
@Override
public ResultVo<?> update(MenuModel model) {
// 调用修改方法
IService.update(model);
return ResultVo.success("修改字典明细数据成功");
return ResultVo.success("修改菜单成功");
}
@ -97,11 +97,11 @@ public class MenuRestController extends BaseRestController<SysMenu, MenuModel, I
* @param id ID
* @return ResultVo
*/
@ApiOperation(value = "删除字典明细数据数据", notes = "删除字典明细数据数据")
@ApiOperation(value = "删除菜单数据", notes = "删除菜单数据")
@Override
public ResultVo<?> del(String id){
IService.delete(id);
return ResultVo.success("删除字典明细数据成功");
return ResultVo.success("删除菜单成功");
}
@ -110,11 +110,11 @@ public class MenuRestController extends BaseRestController<SysMenu, MenuModel, I
* @param ids ID
* @return ResultVo
*/
@ApiOperation(value = "批量删除字典明细数据数据", notes = "批量删除字典明细数据数据")
@ApiOperation(value = "批量删除菜单数据", notes = "批量删除菜单数据")
@Override
public ResultVo<?> delAll(String[] ids){
IService.deleteAll(ids);
return ResultVo.success("批量删除字典明细数据成功");
return ResultVo.success("批量删除菜单成功");
}

@ -36,7 +36,7 @@ public class RoleRestController extends BaseRestController<SysRole, RoleModel, I
* @param model
* @return ResultVo
*/
@ApiOperation(value = "获得单条字典明细数据", notes = "获得单条字典明细数据 - ID")
@ApiOperation(value = "获得单条角色", notes = "获得单条角色 - ID")
@Override
public ResultVo<RoleModel> get(RoleModel model) {
// 如果系统内部调用 则直接查数据库
@ -70,12 +70,12 @@ public class RoleRestController extends BaseRestController<SysRole, RoleModel, I
* @param model
* @return ResultVo
*/
@ApiOperation(value = "新增字典明细数据", notes = "新增字典明细数据")
@ApiOperation(value = "新增角色", notes = "新增角色")
@Override
public ResultVo<?> insert(RoleModel model) {
// 调用新增方法
IService.insert(model);
return ResultVo.success("新增字典明细数据成功");
return ResultVo.success("新增角色成功");
}
/**
@ -83,12 +83,12 @@ public class RoleRestController extends BaseRestController<SysRole, RoleModel, I
* @param model
* @return ResultVo
*/
@ApiOperation(value = "修改字典明细数据", notes = "修改字典明细数据")
@ApiOperation(value = "修改角色", notes = "修改角色")
@Override
public ResultVo<?> update(RoleModel model) {
// 调用修改方法
IService.update(model);
return ResultVo.success("修改字典明细数据成功");
return ResultVo.success("修改角色成功");
}
@ -97,11 +97,11 @@ public class RoleRestController extends BaseRestController<SysRole, RoleModel, I
* @param id ID
* @return ResultVo
*/
@ApiOperation(value = "删除字典明细数据数据", notes = "删除字典明细数据数据")
@ApiOperation(value = "删除角色数据", notes = "删除角色数据")
@Override
public ResultVo<?> del(String id){
IService.delete(id);
return ResultVo.success("删除字典明细数据成功");
return ResultVo.success("删除角色成功");
}
@ -110,11 +110,11 @@ public class RoleRestController extends BaseRestController<SysRole, RoleModel, I
* @param ids ID
* @return ResultVo
*/
@ApiOperation(value = "批量删除字典明细数据数据", notes = "批量删除字典明细数据数据")
@ApiOperation(value = "批量删除角色数据", notes = "批量删除角色数据")
@Override
public ResultVo<?> delAll(String[] ids){
IService.deleteAll(ids);
return ResultVo.success("批量删除字典明细数据成功");
return ResultVo.success("批量删除角色成功");
}

@ -38,7 +38,7 @@ public class UserRestController extends BaseRestController<SysUser, UserModel, I
* @param model
* @return ResultVo
*/
@ApiOperation(value = "获得单条字典明细数据", notes = "获得单条字典明细数据 - ID")
@ApiOperation(value = "获得单条用户信息", notes = "获得单条用户信息 - ID")
@Override
public ResultVo<UserModel> get(UserModel model) {
// 如果系统内部调用 则直接查数据库
@ -72,12 +72,12 @@ public class UserRestController extends BaseRestController<SysUser, UserModel, I
* @param model
* @return ResultVo
*/
@ApiOperation(value = "新增字典明细数据", notes = "新增字典明细数据")
@ApiOperation(value = "新增用户信息", notes = "新增用户信息")
@Override
public ResultVo<?> insert(UserModel model) {
// 调用新增方法
IService.insert(model);
return ResultVo.success("新增字典明细数据成功");
return ResultVo.success("新增用户信息成功");
}
/**
@ -85,12 +85,12 @@ public class UserRestController extends BaseRestController<SysUser, UserModel, I
* @param model
* @return ResultVo
*/
@ApiOperation(value = "修改字典明细数据", notes = "修改字典明细数据")
@ApiOperation(value = "修改用户信息", notes = "修改用户信息")
@Override
public ResultVo<?> update(UserModel model) {
// 调用修改方法
IService.update(model);
return ResultVo.success("修改字典明细数据成功");
return ResultVo.success("修改用户信息成功");
}
@ -99,11 +99,11 @@ public class UserRestController extends BaseRestController<SysUser, UserModel, I
* @param id ID
* @return ResultVo
*/
@ApiOperation(value = "删除字典明细数据数据", notes = "删除字典明细数据数据")
@ApiOperation(value = "删除用户信息数据", notes = "删除用户信息数据")
@Override
public ResultVo<?> del(String id){
IService.delete(id);
return ResultVo.success("删除字典明细数据成功");
return ResultVo.success("删除用户信息成功");
}
@ -112,11 +112,11 @@ public class UserRestController extends BaseRestController<SysUser, UserModel, I
* @param ids ID
* @return ResultVo
*/
@ApiOperation(value = "批量删除字典明细数据数据", notes = "批量删除字典明细数据数据")
@ApiOperation(value = "批量删除用户信息数据", notes = "批量删除用户信息数据")
@Override
public ResultVo<?> delAll(String[] ids){
IService.deleteAll(ids);
return ResultVo.success("批量删除字典明细数据成功");
return ResultVo.success("批量删除用户信息成功");
}

Loading…
Cancel
Save