新增:服务器白名单校验功能
This commit is contained in:
@@ -4,6 +4,8 @@ import cn.hutool.core.util.StrUtil;
|
||||
import com.gxwebsoft.common.core.Constants;
|
||||
import com.gxwebsoft.common.core.config.ConfigProperties;
|
||||
import com.gxwebsoft.common.core.utils.CommonUtil;
|
||||
import com.gxwebsoft.common.core.utils.RedisUtil;
|
||||
import com.gxwebsoft.common.core.utils.SignCheckUtil;
|
||||
import com.gxwebsoft.common.system.entity.LoginRecord;
|
||||
import com.gxwebsoft.common.system.entity.Menu;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
@@ -35,51 +37,63 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
@Component
|
||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
@Resource
|
||||
private ConfigProperties configProperties;
|
||||
@Resource
|
||||
private UserService userService;
|
||||
@Resource
|
||||
private LoginRecordService loginRecordService;
|
||||
@Resource
|
||||
private ConfigProperties configProperties;
|
||||
@Resource
|
||||
private UserService userService;
|
||||
@Resource
|
||||
private LoginRecordService loginRecordService;
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||
throws ServletException, IOException {
|
||||
String access_token = JwtUtil.getAccessToken(request);
|
||||
if (StrUtil.isNotBlank(access_token)) {
|
||||
try {
|
||||
// 解析token
|
||||
Claims claims = JwtUtil.parseToken(access_token, configProperties.getTokenKey());
|
||||
JwtSubject jwtSubject = JwtUtil.getJwtSubject(claims);
|
||||
User user = userService.getByUsername(jwtSubject.getUsername(), jwtSubject.getTenantId());
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException("Username not found");
|
||||
}
|
||||
List<Menu> authorities = user.getAuthorities().stream()
|
||||
.filter(m -> StrUtil.isNotBlank(m.getAuthority())).collect(Collectors.toList());
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||
user, null, authorities);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
// token将要过期签发新token, 防止突然退出登录
|
||||
long expiration = (claims.getExpiration().getTime() - new Date().getTime()) / 1000 / 60;
|
||||
if (expiration < configProperties.getTokenRefreshTime()) {
|
||||
String token = JwtUtil.buildToken(jwtSubject, configProperties.getTokenExpireTime(),
|
||||
configProperties.getTokenKey());
|
||||
response.addHeader(Constants.TOKEN_HEADER_NAME, token);
|
||||
loginRecordService.saveAsync(user.getUsername(), LoginRecord.TYPE_REFRESH, null,
|
||||
user.getTenantId(), request);
|
||||
}
|
||||
} catch (ExpiredJwtException e) {
|
||||
CommonUtil.responseError(response, Constants.TOKEN_EXPIRED_CODE, Constants.TOKEN_EXPIRED_MSG,
|
||||
e.getMessage());
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
CommonUtil.responseError(response, Constants.BAD_CREDENTIALS_CODE, Constants.BAD_CREDENTIALS_MSG,
|
||||
e.toString());
|
||||
return;
|
||||
}
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||
throws ServletException, IOException {
|
||||
String access_token = JwtUtil.getAccessToken(request);
|
||||
if (StrUtil.isNotBlank(access_token)) {
|
||||
try {
|
||||
// 解析token
|
||||
Claims claims = JwtUtil.parseToken(access_token, configProperties.getTokenKey());
|
||||
JwtSubject jwtSubject = JwtUtil.getJwtSubject(claims);
|
||||
|
||||
// 校验服务器白名单
|
||||
final SignCheckUtil checkUtil = new SignCheckUtil();
|
||||
String key = "WhiteDomain:" + jwtSubject.getTenantId();
|
||||
List<String> whiteDomains = redisUtil.get(key, List.class);
|
||||
if (!checkUtil.checkWhiteDomains(whiteDomains, request.getServerName())) {
|
||||
throw new UsernameNotFoundException("The requested domain name is not on the whitelist");
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
|
||||
User user = userService.getByUsername(jwtSubject.getUsername(), jwtSubject.getTenantId());
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException("Username not found");
|
||||
}
|
||||
List<Menu> authorities = user.getAuthorities().stream()
|
||||
.filter(m -> StrUtil.isNotBlank(m.getAuthority())).collect(Collectors.toList());
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||
user, null, authorities);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
|
||||
// token将要过期签发新token, 防止突然退出登录
|
||||
long expiration = (claims.getExpiration().getTime() - new Date().getTime()) / 1000 / 60;
|
||||
if (expiration < configProperties.getTokenRefreshTime()) {
|
||||
String token = JwtUtil.buildToken(jwtSubject, configProperties.getTokenExpireTime(),
|
||||
configProperties.getTokenKey());
|
||||
response.addHeader(Constants.TOKEN_HEADER_NAME, token);
|
||||
loginRecordService.saveAsync(user.getUsername(), LoginRecord.TYPE_REFRESH, null,
|
||||
user.getTenantId(), request);
|
||||
}
|
||||
} catch (ExpiredJwtException e) {
|
||||
CommonUtil.responseError(response, Constants.TOKEN_EXPIRED_CODE, Constants.TOKEN_EXPIRED_MSG,
|
||||
e.getMessage());
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
CommonUtil.responseError(response, Constants.BAD_CREDENTIALS_CODE, Constants.BAD_CREDENTIALS_MSG,
|
||||
e.toString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import com.gxwebsoft.common.system.entity.KVEntity;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -169,4 +170,24 @@ public class SignCheckUtil {
|
||||
return sign.equals(getWXSignString(params, key));
|
||||
}
|
||||
|
||||
/**
|
||||
* 白名单校验
|
||||
* @param domainName abc.com
|
||||
* @return true
|
||||
*/
|
||||
public boolean checkWhiteDomains(List<String> whiteDomains, String domainName) {
|
||||
if(whiteDomains == null){
|
||||
return true;
|
||||
}
|
||||
if (whiteDomains.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
for(String item: whiteDomains){
|
||||
if(Objects.equals(item, domainName)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,8 +32,6 @@ public class BaseController {
|
||||
@Resource
|
||||
private HttpServletRequest request;
|
||||
@Resource
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
@Resource
|
||||
private UserService userService;
|
||||
@Resource
|
||||
private CompanyService companyService;
|
||||
@@ -222,6 +220,8 @@ public class BaseController {
|
||||
return request.getParameter("sign");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 根据账号|手机号码|邮箱查找用户ID
|
||||
*
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.gxwebsoft.common.core.security.JwtUtil;
|
||||
import com.gxwebsoft.common.core.utils.CacheClient;
|
||||
import com.gxwebsoft.common.core.utils.CommonUtil;
|
||||
import com.gxwebsoft.common.core.utils.RedisUtil;
|
||||
import com.gxwebsoft.common.core.utils.SignCheckUtil;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.ExistenceParam;
|
||||
@@ -39,20 +40,19 @@ import com.wf.captcha.SpecCaptcha;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import net.sf.jsqlparser.expression.LongValue;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@@ -155,7 +155,7 @@ public class MainController extends BaseController {
|
||||
|
||||
@ApiOperation("获取当前租户信息")
|
||||
@GetMapping("/auth/tenant")
|
||||
public ApiResult<?> tenant() {
|
||||
public ApiResult<?> tenant(HttpServletRequest request) {
|
||||
Integer tenantId = getTenantId();
|
||||
if (tenantId == null) {
|
||||
return fail("缺少参数tenantId",null);
|
||||
@@ -167,7 +167,7 @@ public class MainController extends BaseController {
|
||||
// 企业信息
|
||||
Company company = companyService.getByTenantIdRel(tenantId);
|
||||
if(company == null){
|
||||
return fail("该租户不存在或已过期",null);
|
||||
return fail("该企业不存在!",null);
|
||||
}
|
||||
company.setBusinessEntity(null);
|
||||
company.setPhone(null);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.gxwebsoft.common.system.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.gxwebsoft.common.core.utils.RedisUtil;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.common.system.service.WhiteDomainService;
|
||||
@@ -17,6 +19,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 服务器白名单控制器
|
||||
@@ -26,10 +29,12 @@ import java.util.List;
|
||||
*/
|
||||
@Api(tags = "服务器白名单管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/common.system/white-domain")
|
||||
@RequestMapping("/api/system/white-domain")
|
||||
public class WhiteDomainController extends BaseController {
|
||||
@Resource
|
||||
private WhiteDomainService whiteDomainService;
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@PreAuthorize("hasAuthority('sys:whiteDomain:list')")
|
||||
@ApiOperation("分页查询服务器白名单")
|
||||
@@ -60,12 +65,18 @@ public class WhiteDomainController extends BaseController {
|
||||
@ApiOperation("添加服务器白名单")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody WhiteDomain whiteDomain) {
|
||||
String key = "WhiteDomain:";
|
||||
// 记录当前登录用户id
|
||||
User loginUser = getLoginUser();
|
||||
if (loginUser != null) {
|
||||
key = key + loginUser.getTenantId();
|
||||
whiteDomain.setUserId(loginUser.getUserId());
|
||||
}
|
||||
if (whiteDomainService.save(whiteDomain)) {
|
||||
// 重写缓存
|
||||
final List<WhiteDomain> list = whiteDomainService.list();
|
||||
final List<String> collect = list.stream().map(WhiteDomain::getDomain).collect(Collectors.toList());
|
||||
redisUtil.set(key,collect);
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
@@ -88,6 +99,15 @@ public class WhiteDomainController extends BaseController {
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (whiteDomainService.removeById(id)) {
|
||||
// 重写缓存
|
||||
String key = "WhiteDomain:";
|
||||
User loginUser = getLoginUser();
|
||||
if (loginUser != null) {
|
||||
key = key + loginUser.getTenantId();
|
||||
}
|
||||
final List<WhiteDomain> list = whiteDomainService.list();
|
||||
final List<String> collect = list.stream().map(WhiteDomain::getDomain).collect(Collectors.toList());
|
||||
redisUtil.set(key,collect);
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
|
||||
Reference in New Issue
Block a user