You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
4.9 KiB
147 lines
4.9 KiB
/**
|
|
* Copyright (c) 2018 人人开源 All rights reserved.
|
|
*
|
|
* https://www.renren.io
|
|
*
|
|
* 版权所有,侵权必究!
|
|
*/
|
|
|
|
package com.epmet.service.impl;
|
|
|
|
import io.jsonwebtoken.Claims;
|
|
import com.epmet.commons.tools.constant.Constant;
|
|
import com.epmet.commons.tools.enums.SuperAdminEnum;
|
|
import com.epmet.commons.tools.exception.ErrorCode;
|
|
import com.epmet.commons.tools.exception.RenException;
|
|
import com.epmet.commons.tools.redis.UserDetailRedis;
|
|
import com.epmet.commons.tools.security.bo.ResourceBO;
|
|
import com.epmet.commons.tools.security.enums.ResourceAuthEnum;
|
|
import com.epmet.commons.tools.security.enums.UserKillEnum;
|
|
import com.epmet.commons.tools.security.user.UserDetail;
|
|
import com.epmet.commons.tools.utils.Result;
|
|
import com.epmet.feign.ResourceFeignClient;
|
|
import com.epmet.feign.UserFeignClient;
|
|
import com.epmet.jwt.JwtUtils;
|
|
import com.epmet.service.ResourceService;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.util.AntPathMatcher;
|
|
|
|
import java.util.List;
|
|
|
|
/**
|
|
* 资源服务
|
|
*
|
|
* @author Mark sunlightcs@gmail.com
|
|
* @since 1.0.0
|
|
*/
|
|
@Service
|
|
public class ResourceServiceImpl implements ResourceService {
|
|
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
|
|
@Autowired
|
|
private UserFeignClient userFeignClient;
|
|
@Autowired
|
|
private ResourceFeignClient resourceFeignClient;
|
|
@Autowired
|
|
private UserDetailRedis userDetailRedis;
|
|
@Autowired
|
|
private JwtUtils jwtUtils;
|
|
|
|
@Override
|
|
public UserDetail resource(String token, String url, String method) {
|
|
//1、获取所有资源列表
|
|
List<ResourceBO> resourceList = resourceFeignClient.list();
|
|
|
|
//2、判断是否在资源列表里
|
|
ResourceBO resource = pathMatcher(url, method, resourceList);
|
|
|
|
//3、无需登录认证
|
|
if(resource != null && resource.getAuthLevel() == ResourceAuthEnum.NO_AUTH.value()){
|
|
return null;
|
|
}
|
|
|
|
//4、获取用户信息
|
|
UserDetail userDetail = getUserDetail(token);
|
|
|
|
//5、登录认证
|
|
if(resource != null && resource.getAuthLevel() == ResourceAuthEnum.LOGIN_AUTH.value()){
|
|
return userDetail;
|
|
}
|
|
|
|
//6、不在资源列表里,只要登录了,就有权限访问
|
|
if(resource == null){
|
|
return userDetail;
|
|
}
|
|
|
|
//7、当前登录用户是超级管理员
|
|
if(userDetail.getSuperAdmin() == SuperAdminEnum.YES.value()){
|
|
return userDetail;
|
|
}
|
|
|
|
//8、需要鉴权,获取用户资源列表
|
|
List<ResourceBO> userResourceList = userDetail.getResourceList();
|
|
|
|
//9、如果不在用户资源列表里,则无权访问
|
|
resource = pathMatcher(url, method, userResourceList);
|
|
if(resource != null){
|
|
return userDetail;
|
|
}
|
|
|
|
throw new RenException(ErrorCode.FORBIDDEN);
|
|
}
|
|
|
|
/**
|
|
* 根据token,获取用户信息
|
|
* @param token 用户token
|
|
* @return 返回用户信息
|
|
*/
|
|
private UserDetail getUserDetail(String token) {
|
|
//token为空
|
|
if(StringUtils.isBlank(token)){
|
|
throw new RenException(ErrorCode.NOT_NULL, Constant.TOKEN_HEADER);
|
|
}
|
|
|
|
//是否过期
|
|
Claims claims = jwtUtils.getClaimByToken(token);
|
|
if(claims == null || jwtUtils.isTokenExpired(claims.getExpiration())){
|
|
throw new RenException(ErrorCode.UNAUTHORIZED);
|
|
}
|
|
|
|
//获取用户ID
|
|
Long userId = Long.parseLong(claims.getSubject());
|
|
|
|
//查询Redis,如果没数据,则保持用户信息到Redis
|
|
UserDetail userDetail = userDetailRedis.get(userId);
|
|
if(userDetail == null){
|
|
//获取用户信息
|
|
Result<UserDetail> result = userFeignClient.getById(userId);
|
|
userDetail = result.getData();
|
|
if(userDetail == null){
|
|
throw new RenException(ErrorCode.ACCOUNT_NOT_EXIST);
|
|
}
|
|
|
|
//过期时间
|
|
long expire = (claims.getExpiration().getTime() - System.currentTimeMillis())/1000;
|
|
userDetailRedis.set(userDetail, expire);
|
|
}
|
|
|
|
//Redis有数据,则判断是否被踢出,如果被踢出,则提示重新登录
|
|
if(userDetail.getKill() == UserKillEnum.YES.value()){
|
|
throw new RenException(ErrorCode.UNAUTHORIZED);
|
|
}
|
|
|
|
return userDetail;
|
|
}
|
|
|
|
private ResourceBO pathMatcher(String url, String method, List<ResourceBO> resourceList){
|
|
for (ResourceBO resource : resourceList) {
|
|
if (StringUtils.isNotBlank(resource.getResourceUrl()) && antPathMatcher.match(resource.getResourceUrl(), url)
|
|
&& method.equalsIgnoreCase(resource.getResourceMethod())) {
|
|
return resource;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
}
|
|
|