修复了一些已知的安全问题
1. 🔒 安全问题处理 2. ✨ 我的钱包接口
This commit is contained in:
commit
547f11abe4
@ -7,6 +7,7 @@ import com.rymcu.forest.core.result.GlobalResult;
|
||||
import com.rymcu.forest.core.result.ResultCode;
|
||||
import com.rymcu.forest.enumerate.TransactionCode;
|
||||
import com.rymcu.forest.web.api.exception.BaseApiException;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.shiro.authz.UnauthenticatedException;
|
||||
import org.apache.shiro.authz.UnauthorizedException;
|
||||
import org.slf4j.Logger;
|
||||
@ -39,9 +40,9 @@ public class BaseExceptionHandler {
|
||||
if (isAjax(request)) {
|
||||
GlobalResult result = new GlobalResult();
|
||||
if (ex instanceof BaseApiException) {
|
||||
result.setCode(401);
|
||||
result.setMessage("用户未登录");
|
||||
logger.info("用户未登录");
|
||||
result.setCode(((BaseApiException) ex).getCode());
|
||||
result.setMessage(((BaseApiException) ex).getExtraMessage());
|
||||
logger.info(result.getMessage());
|
||||
} else if (ex instanceof UnauthenticatedException) {
|
||||
result.setCode(1000001);
|
||||
result.setMessage("token错误");
|
||||
@ -88,8 +89,8 @@ public class BaseExceptionHandler {
|
||||
FastJsonJsonView view = new FastJsonJsonView();
|
||||
Map<String, Object> attributes = new HashMap(2);
|
||||
if (ex instanceof BaseApiException) {
|
||||
attributes.put("code", "401");
|
||||
attributes.put("message", "用户未登录");
|
||||
attributes.put("code", ((BaseApiException) ex).getCode());
|
||||
attributes.put("message", ((BaseApiException) ex).getExtraMessage());
|
||||
} else if (ex instanceof UnauthenticatedException) {
|
||||
attributes.put("code", "1000001");
|
||||
attributes.put("message", "token错误");
|
||||
@ -138,8 +139,8 @@ public class BaseExceptionHandler {
|
||||
String requestedWith = request.getHeader("x-requested-with");
|
||||
if (requestedWith != null && "XMLHttpRequest".equalsIgnoreCase(requestedWith)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
String contentType = request.getContentType();
|
||||
return StringUtils.isNotBlank(contentType) && contentType.contains("application/json");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,109 @@
|
||||
package com.rymcu.forest.core.service.security;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.rymcu.forest.dto.TokenUser;
|
||||
import com.rymcu.forest.jwt.def.JwtConstants;
|
||||
import com.rymcu.forest.util.UserUtils;
|
||||
import com.rymcu.forest.web.api.exception.BaseApiException;
|
||||
import com.rymcu.forest.web.api.exception.ErrorCode;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 检查用户修改信息权限
|
||||
*
|
||||
* @author ronger
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class SecurityAspect {
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(SecurityAspect.class);
|
||||
|
||||
@Pointcut("@annotation(com.rymcu.forest.core.service.security.annotation.SecurityInterceptor)")
|
||||
public void pointCut() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户修改信息权限
|
||||
*
|
||||
* @param joinPoint 连接点
|
||||
* @return 方法执行结果
|
||||
* @throws Throwable 调用出错
|
||||
*/
|
||||
@Before(value = "pointCut()")
|
||||
public void doBefore(JoinPoint joinPoint) throws BaseApiException {
|
||||
logger.info("检查用户修改信息权限 start ...");
|
||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
String idUser = "";
|
||||
if (isAjax(request)) {
|
||||
Object[] objects = joinPoint.getArgs();
|
||||
JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(objects[0]));
|
||||
if (Objects.nonNull(jsonObject)) {
|
||||
idUser = jsonObject.getString("idUser");
|
||||
}
|
||||
} else {
|
||||
Map params = getParams(request);
|
||||
if (params.isEmpty()) {
|
||||
params = (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
} else {
|
||||
params.putAll((Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE));
|
||||
}
|
||||
idUser = (String) params.get("idUser");
|
||||
}
|
||||
if (Objects.nonNull(idUser)) {
|
||||
String authHeader = request.getHeader(JwtConstants.AUTHORIZATION);
|
||||
if (StringUtils.isNotBlank(authHeader)) {
|
||||
TokenUser tokenUser = UserUtils.getTokenUser(authHeader);
|
||||
if (Objects.nonNull(tokenUser)) {
|
||||
if (!idUser.equals(tokenUser.getIdUser().toString())) {
|
||||
throw new BaseApiException(ErrorCode.ACCESS_DENIED);
|
||||
}
|
||||
} else {
|
||||
throw new BaseApiException(ErrorCode.ACCESS_DENIED);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new BaseApiException(ErrorCode.ACCESS_DENIED);
|
||||
}
|
||||
logger.info("检查用户修改信息权限 end ...");
|
||||
}
|
||||
|
||||
private Map<String, String> getParams(HttpServletRequest request) {
|
||||
Map<String, String> paramsMap = new HashMap<>(10);
|
||||
Enumeration<String> paraNames = request.getParameterNames();
|
||||
while (paraNames.hasMoreElements()) {
|
||||
String key = paraNames.nextElement();
|
||||
if ("password".equals(key)) {
|
||||
continue;
|
||||
}
|
||||
paramsMap.put(key, request.getParameter(key));
|
||||
}
|
||||
return paramsMap;
|
||||
}
|
||||
|
||||
private boolean isAjax(HttpServletRequest request) {
|
||||
String requestedWith = request.getHeader("x-requested-with");
|
||||
if (requestedWith != null && "XMLHttpRequest".equalsIgnoreCase(requestedWith)) {
|
||||
return true;
|
||||
}
|
||||
String contentType = request.getContentType();
|
||||
return StringUtils.isNotBlank(contentType) && contentType.contains("application/json");
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.rymcu.forest.core.service.security.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* 安全拦截器
|
||||
* @author ronger
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SecurityInterceptor {
|
||||
}
|
@ -66,10 +66,10 @@ public class RestAuthTokenInterceptor implements HandlerInterceptor {
|
||||
request.setAttribute(JwtConstants.CURRENT_TOKEN_CLAIMS, claims);
|
||||
//如果token验证成功,将token对应的用户id存在request中,便于之后注入
|
||||
request.setAttribute(JwtConstants.CURRENT_USER_NAME, model.getUsername());
|
||||
String uri = request.getRequestURI();
|
||||
// 判断是否为后台接口或财政划转接口
|
||||
String adminApi = "/admin";
|
||||
String transactionApi = "/transaction";
|
||||
String uri = request.getRequestURI();
|
||||
if (uri.contains(adminApi) || uri.contains(transactionApi)) {
|
||||
// 判断管理员权限
|
||||
boolean hasPermission = userMapper.hasAdminPermission(model.getUsername());
|
||||
|
@ -0,0 +1,35 @@
|
||||
package com.rymcu.forest.web.api.bank;
|
||||
|
||||
import com.rymcu.forest.core.result.GlobalResult;
|
||||
import com.rymcu.forest.core.result.GlobalResultGenerator;
|
||||
import com.rymcu.forest.core.service.security.annotation.SecurityInterceptor;
|
||||
import com.rymcu.forest.dto.BankAccountDTO;
|
||||
import com.rymcu.forest.service.BankAccountService;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* Created on 2021/12/10 19:25.
|
||||
*
|
||||
* @author ronger
|
||||
* @email ronger-x@outlook.com
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/wallet")
|
||||
public class WalletController {
|
||||
|
||||
@Resource
|
||||
private BankAccountService bankAccountService;
|
||||
|
||||
|
||||
@GetMapping("/{idUser}")
|
||||
@SecurityInterceptor
|
||||
public GlobalResult detail(@PathVariable Integer idUser) {
|
||||
BankAccountDTO bankAccount = bankAccountService.findBankAccountByIdUser(idUser);
|
||||
return GlobalResultGenerator.genSuccessResult(bankAccount);
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ package com.rymcu.forest.web.api.exception;
|
||||
|
||||
/**
|
||||
* 服务(业务)异常如“ 账号或密码错误 ”,该异常只做INFO级别的日志记录 @see WebMvcConfigurer
|
||||
* @author ronger
|
||||
*/
|
||||
public class BaseApiException extends Exception {
|
||||
|
||||
|
@ -2,6 +2,7 @@ package com.rymcu.forest.web.api.user;
|
||||
|
||||
import com.rymcu.forest.core.result.GlobalResult;
|
||||
import com.rymcu.forest.core.result.GlobalResultGenerator;
|
||||
import com.rymcu.forest.core.service.security.annotation.SecurityInterceptor;
|
||||
import com.rymcu.forest.dto.*;
|
||||
import com.rymcu.forest.entity.UserExtend;
|
||||
import com.rymcu.forest.service.UserService;
|
||||
@ -21,36 +22,42 @@ public class UserInfoController {
|
||||
private UserService userService;
|
||||
|
||||
@GetMapping("/detail/{idUser}")
|
||||
@SecurityInterceptor
|
||||
public GlobalResult detail(@PathVariable Integer idUser) {
|
||||
Map map = userService.findUserInfo(idUser);
|
||||
return GlobalResultGenerator.genSuccessResult(map);
|
||||
}
|
||||
|
||||
@GetMapping("/check-nickname")
|
||||
@SecurityInterceptor
|
||||
public GlobalResult checkNickname(@RequestParam Integer idUser, @RequestParam String nickname) {
|
||||
Map map = userService.checkNickname(idUser,nickname);
|
||||
return GlobalResultGenerator.genSuccessResult(map);
|
||||
}
|
||||
|
||||
@PatchMapping("/update")
|
||||
@SecurityInterceptor
|
||||
public GlobalResult updateUserInfo(@RequestBody UserInfoDTO user) {
|
||||
Map map = userService.updateUserInfo(user);
|
||||
return GlobalResultGenerator.genSuccessResult(map);
|
||||
}
|
||||
|
||||
@PatchMapping("/update-extend")
|
||||
@SecurityInterceptor
|
||||
public GlobalResult updateUserExtend(@RequestBody UserExtend userExtend) {
|
||||
Map map = userService.updateUserExtend(userExtend);
|
||||
return GlobalResultGenerator.genSuccessResult(map);
|
||||
}
|
||||
|
||||
@PatchMapping("/update-email")
|
||||
@SecurityInterceptor
|
||||
public GlobalResult updateEmail(@RequestBody ChangeEmailDTO changeEmailDTO) {
|
||||
Map map = userService.updateEmail(changeEmailDTO);
|
||||
return GlobalResultGenerator.genSuccessResult(map);
|
||||
}
|
||||
|
||||
@PatchMapping("/update-password")
|
||||
@SecurityInterceptor
|
||||
public GlobalResult updatePassword(@RequestBody UpdatePasswordDTO updatePasswordDTO) {
|
||||
Map map = userService.updatePassword(updatePasswordDTO);
|
||||
return GlobalResultGenerator.genSuccessResult(map);
|
||||
|
Loading…
Reference in New Issue
Block a user