服务端校验密码,成功后存储token到redis(失效时间为1天)并返回token给客户端
通过自定义拦截器,拦截所有请求,并对需要鉴权的API做token鉴权逻辑处理,存在改token则通过请求,不存在则需要做刷新token或生成token处理
用户传入appid和appkey来生成token,服务端通过appid和appkey来到mysql中查找该用户的接口权限,如果满足访问该接口权限则生成token并存储到redis,失效时间为1天,并返回给客户端
用户通过appid和appkey来查询token,服务端通过appid和appkey来到mysql中查找该用户的接口权限,如果满足访问该接口权限则根据appid到redis中获取当前的token,并返回给客户端
用户通过appid和appkey来查询token,服务端通过appid和appkey来到mysql中查找该用户的接口权限,如果满足访问该接口权限则到redis中删除对应的token信息
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author gk
* @note 加上该注解的类http请求时需要进行token鉴权
* @date 2021/9/16 10:14
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthToken {
}
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* @author gk
* @note token的controller
* @date 2021/6/26 11:14
*/
@RestController
@RequestMapping(value = "/usr/token", produces = "application/json; charset=utf-8")
public class TokenChargingController {
private final TokenService tokenService;
public TokenChargingController(TokenService tokenService) {
this.tokenService = tokenService;
}
/**
* 生成我们自己的token
* @return
*/
@RequestMapping(value = "/create_token", method = RequestMethod.GET)
@ApiOperation(value = "生成token", notes = "生成token值")
public Object createToken(
HttpServletRequest request,
@ApiParam(name = "appid", value = "appid", required = true) @RequestHeader(value = "appid") String appid,
@ApiParam(name = "appkey", value = "appkey", required = true) @RequestHeader(value = "appkey") String appkey) {
Map<String, Object> resultMap = new HashMap<>();
CacheService cacheService = = null;
try {
cacheService = new JedisPoolUtils();
// 初始化:URI、URL、addr
String uri = request.getRequestURI();
resultMap.put("AppId", appid);
resultMap.put("AppKey", appkey);
// 查询用户权限是否有效:appid、appkey、uri
ApiUserUriMapping apiUserUriMapping = this.tokenService.getApiUserUriMapping(appid, appkey, uri);
if (apiUserUriMapping == null) {
resultMap.put("StatusCode", CommonEnum.SIGNATURE_NOT_MATCH.getResultCode());
resultMap.put("AccessToken", "");
resultMap.put("TokenAvailableTime", "");
resultMap.put("Msg", CommonEnum.SIGNATURE_NOT_MATCH.getResultMsg());
} else {
// 创建token
String token = this.tokenService.createToken(cacheService, appid, appkey);
resultMap.put("StatusCode", CommonEnum.SUCCESS.getResultCode());
resultMap.put("AccessToken", token);
resultMap.put("TokenAvailableTime", cacheService.ttl(token, RedisDbConstant.DB_10) + "");
resultMap.put("Msg", CommonEnum.SUCCESS.getResultMsg());
}
} catch (Exception e) {
resultMap.put("StatusCode", CommonEnum.INTERNAL_SERVER_ERROR.getResultCode());
resultMap.put("AccessToken", "");
resultMap.put("TokenAvailableTime", "");
resultMap.put("Msg", CommonEnum.INTERNAL_SERVER_ERROR.getResultMsg());
} finally {
if (Objects.nonNull(cacheService))
cacheService.destroy();
}
return resultMap;
}
/**
* 查询token
* @return
*/
@RequestMapping(value = "/query_token", method = RequestMethod.GET)
@ApiOperation(value = "获取token", notes = "获取token值")
public Object queryToken(
HttpServletRequest request,
@ApiParam(name = "appid", value = "appid", required = true) @RequestHeader(value = "appid") String appid,
@ApiParam(name = "appkey", value = "appkey", required = true) @RequestHeader(value = "appkey") String appkey) {
Map<String, Object> resultMap = new HashMap<>();
CacheService cacheService = null;
try {
cacheService = new JedisPoolUtils();
// 初始化:URI、URL、addr
String uri = request.getRequestURI();
resultMap.put("AppId", appid);
resultMap.put("AppKey", appkey);
// 查询用户权限是否有效:appid、appkey、uri
ApiUserUriMapping apiUserUriMapping = this.tokenService.getApiUserUriMapping(appid, appkey, uri);
if (apiUserUriMapping == null) {
resultMap.put("StatusCode", CommonEnum.SIGNATURE_NOT_MATCH.getResultCode());
resultMap.put("AccessToken", "");
resultMap.put("TokenAvailableTime", "");
resultMap.put("Msg", CommonEnum.SIGNATURE_NOT_MATCH.getResultMsg());
} else {
// 查询token
String token = this.tokenService.queryToken(cacheService, appid);
resultMap.put("StatusCode", CommonEnum.SUCCESS.getResultCode());
resultMap.put("AccessToken", token);
resultMap.put("TokenAvailableTime", cacheService.ttl(token, RedisDbConstant.DB_10) + "");
resultMap.put("Msg", CommonEnum.SUCCESS.getResultMsg());
}
} catch (Exception e) {
resultMap.put("StatusCode", CommonEnum.INTERNAL_SERVER_ERROR.getResultCode());
resultMap.put("AccessToken", "");
resultMap.put("TokenAvailableTime", "");
resultMap.put("Msg", CommonEnum.INTERNAL_SERVER_ERROR.getResultMsg());
} finally {
if (Objects.nonNull(cacheService))
cacheService.destroy();
}
return resultMap;
}
@RequestMapping(value = "/logout_user", method = RequestMethod.GET)
@ApiOperation(value = "用户注销", notes = "用户注销")
public Object logoutUser(
HttpServletRequest request,
@ApiParam(name = "appid", value = "appid", required = true) @RequestHeader(value = "appid") String appid,
@ApiParam(name = "appkey", value = "appkey", required = true) @RequestHeader(value = "appkey") String appkey) {
Map<String, Object> resultMap = new HashMap<>();
CacheService cacheService = null;
try {
cacheService = new JedisPoolUtils();
// 初始化:URI、URL、addr
String uri = request.getRequestURI();
resultMap.put("AppId", appid);
resultMap.put("AppKey", appkey);
// 查询用户权限是否有效:appid、appkey、uri
ApiUserUriMapping apiUserUriMapping = this.tokenService.getApiUserUriMapping(appid, appkey, uri);
if (apiUserUriMapping == null) {
resultMap.put("StatusCode", CommonEnum.SIGNATURE_NOT_MATCH.getResultCode());
resultMap.put("AccessToken", "");
resultMap.put("TokenAvailableTime", "");
resultMap.put("Msg", CommonEnum.SIGNATURE_NOT_MATCH.getResultMsg());
} else {
// 创建token
boolean isSuccess = this.tokenService.logoutUser(cacheService, appid);
resultMap.put("StatusCode", isSuccess ? CommonEnum.SUCCESS.getResultCode() : CommonEnum.INTERNAL_SERVER_ERROR.getResultCode());
resultMap.put("AccessToken", "");
resultMap.put("TokenAvailableTime", "");
resultMap.put("Msg", isSuccess ? CommonEnum.SUCCESS.getResultMsg() : CommonEnum.INTERNAL_SERVER_ERROR.getResultMsg());
}
} catch (Exception e) {
resultMap.put("StatusCode", CommonEnum.INTERNAL_SERVER_ERROR.getResultCode());
resultMap.put("AccessToken", "");
resultMap.put("TokenAvailableTime", "");
resultMap.put("Msg", CommonEnum.INTERNAL_SERVER_ERROR.getResultMsg());
} finally {
if (Objects.nonNull(cacheService))
cacheService.destroy();
}
return resultMap;
}
}
public interface TokenService {
/**
* 权限验证:查询用户的接口访问权限信息
*
* @param appid 用户ID
* @param appkey 用户KEY
* @param uri 请求路径URI
* @return ApiUserUriMapping
*/
ApiUserUriMapping getApiUserUriMapping(
String appid,
String appkey,
String uri);
/**
* 创建token
*
* @param appid
* @param appkey
* @return token
*/
String createToken(CacheService cacheService, String appid, String appkey) throws Exception;
/**
* 查询token
*
* @param appid
* @return token
*/
String queryToken(CacheService cacheService, String appid) throws Exception;
/**
* 查询token
*
* @param appid
* @return token
*/
boolean logoutUser(CacheService cacheService, String appid) throws Exception;
}
@Service
public class TokenServiceImpl implements TokenService {
private final VBApiUserUriMappingMapper vbApiUserUriMappingMapper;
@Autowired
public ApiUserUriMappingServiceImpl(
VBApiUserUriMappingMapper vbApiUserUriMappingMapper) {
this.vbApiUserUriMappingMapper = vbApiUserUriMappingMapper;
}
@Override
public ApiUserUriMapping getApiUserUriMapping(String appid, String appkey, String uri) {
List<Map> lists = this.getVBApiUserUriMappingByMap(
new HashMap<String, String>() {
{
put("appid", appid);
put("appkey", appkey);
put("uri", uri);
}
}
);
return CollectionUtils.isEmpty(lists) ?
null : JSONObject.parseObject(JSONObject.toJSONString(lists.get(0)), ApiUserUriMapping.class);
}
@Override
public String createToken(CacheService cacheService, String user, String key) throws Exception {
String token = "";
Random random = new Random();
double v = random.nextDouble();
//获取当前时间时间
String currentDate = DateUtils.getCurrentDate("yyyy-MM-dd HH:mm:ss");
String md = user + "+" + key + "#" + currentDate + "%" + v + "@";
//md5加密
String mdToken = Md5Util.MD5(md);
//MD5二次加密
token = Md5Util.MD5(mdToken);
//删除老的token
String oldToken = cacheService.get(TokenConstant.CURRENT_TOKEN_PREFIX + user, RedisDbConstant.DB_10);
if (StringUtils.isNotBlank(oldToken))
cacheService.del(oldToken, RedisDbConstant.DB_10);
//更新redis
cacheService.hset(token, UserFieldConstant.APP_ID, user, RedisDbConstant.DB_10);
cacheService.hset(token, UserFieldConstant.APP_KEY, key, RedisDbConstant.DB_10);
cacheService.hset(token, UserFieldConstant.TOKEN, token, RedisDbConstant.DB_10);
cacheService.hset(token, UserFieldConstant.UPDATE_TIME, currentDate, RedisDbConstant.DB_10);
//设置失效时间
cacheService.expire(token, TokenConstant.ONE_DAY, RedisDbConstant.DB_10);
//设置当前用户使用的token
cacheService.set(TokenConstant.ONE_DAY, TokenConstant.CURRENT_TOKEN_PREFIX + user, token, RedisDbConstant.DB_10);
return token;
}
@Override
public String queryToken(CacheService cacheService, String appid) throws Exception {
String token = "";
String redisKey = TokenConstant.CURRENT_TOKEN_PREFIX + appid;
if (cacheService.exists(redisKey, RedisDbConstant.DB_10))
token = cacheService.get(redisKey, RedisDbConstant.DB_10);
return token;
}
@Override
public boolean logoutUser(CacheService cacheService, String appid) throws Exception {
boolean isLogout = false;
String redisKey = TokenConstant.CURRENT_TOKEN_PREFIX + appid;
if (cacheService.exists(redisKey, RedisDbConstant.DB_10))
cacheService.del(redisKey, RedisDbConstant.DB_10);
isLogout = true;
return isLogout ;
}
private List<Map> getVBApiUserUriMappingByMap(Map map) {
return this.vbApiUserUriMappingMapper.getAllByParam(
ObjectUtils.isEmpty(map.get("id")) ? null : map.get("id").toString(),
ObjectUtils.isEmpty(map.get("appid")) ? null : map.get("appid").toString(),
ObjectUtils.isEmpty(map.get("appkey")) ? null : map.get("appkey").toString(),
ObjectUtils.isEmpty(map.get("userType")) ? null : map.get("userType").toString(),
ObjectUtils.isEmpty(map.get("userName")) ? null : map.get("userName").toString(),
ObjectUtils.isEmpty(map.get("userUnit")) ? null : map.get("userUnit").toString(),
ObjectUtils.isEmpty(map.get("phone")) ? null : map.get("phone").toString(),
ObjectUtils.isEmpty(map.get("createTime")) ? null : map.get("createTime").toString(),
ObjectUtils.isEmpty(map.get("updTime")) ? null : map.get("updTime").toString(),
ObjectUtils.isEmpty(map.get("beginTime")) ? null : map.get("beginTime").toString(),
ObjectUtils.isEmpty(map.get("endTime")) ? null : map.get("endTime").toString(),
ObjectUtils.isEmpty(map.get("accessIpList")) ? null : map.get("accessIpList").toString(),
ObjectUtils.isEmpty(map.get("uri")) ? null : map.get("uri").toString(),
ObjectUtils.isEmpty(map.get("uriUserConfig")) ? null : map.get("uriUserConfig").toString(),
ObjectUtils.isEmpty(map.get("formatCls")) ? null : map.get("formatCls").toString(),
ObjectUtils.isEmpty(map.get("opType")) ? null : map.get("opType").toString());
}
}
/**
* @author gk
* @note 登陆过滤器
* @date 2021/09/16 11:14
*/
@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
@Autowired
private ApiUserUriService apiUserUriService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
// 如果打上了AuthToken注解则需要验证token
if (method.getAnnotation(AuthToken.class) != null || handlerMethod.getBeanType().getAnnotation(AuthToken.class) != null) {
CacheService cacheService = new JedisPoolUtils();
try {
//从header中拿token,并进行解析
String token = request.getHeader(TokenConstant.TOKEN);
if (StringUtils.isBlank(token)) {
reSetResponse(response, CommonEnum.SIGNATURE_NOT_MATCH);
return false;
}
if (!cacheService.exists(token, RedisDbConstant.DB_10)) {
reSetResponse(response, CommonEnum.NO_USER);
return false;
}
String uri = request.getRequestURI();
String appid = cacheService.hget(token, UserFieldConstant.APP_ID, RedisDbConstant.DB_10);
String appkey = cacheService.hget(token, UserFieldConstant.APP_KEY, RedisDbConstant.DB_10);
if (StringUtils.isBlank(appid) || StringUtils.isBlank(appkey)) {
reSetResponse(response, CommonEnum.NOT_PERMISSION);
return false;
}
// 查询用户权限是否有效:appid、appkey、uri
ApiUserUriMapping apiUserUriMapping = this.apiUserUriService.getApiUserUriMapping(appid, appkey, uri);
if (Objects.isNull(apiUserUriMapping)) {
reSetResponse(response, CommonEnum.NOT_PERMISSION);
return false;
}
//dataRange|appid|appkey
String dataRange = apiUserUriMapping.getUriUserConfig();
Map<String, String> key = new HashMap<>();
key.put("dataRange", dataRange);
key.put("appid", appid);
key.put("appkey", appkey);
key.put("token", token);
key.put("className", apiUserUriMapping.getFormatCls());
request.setAttribute(TokenConstant.REQUEST_CURRENT_KEY, key);
} catch (Exception e) {
e.printStackTrace();
reSetResponse(response, CommonEnum.INTERNAL_SERVER_ERROR);
return false;
} finally {
cacheService.destroy();
}
return true;
}
if (StringUtils.isNotBlank(request.getRequestURI()) && request.getRequestURI().endsWith("/v2/api-docs")) {
//swagger自带的api-docs
// 查询用户权限是否有效:appid、appkey、uri
String appid = request.getHeader("appid");
String appkey = request.getHeader("appkey");
if (StringUtils.isBlank(appid) || StringUtils.isBlank(appkey)) {
reSetResponse(response, CommonEnum.SIGNATURE_NOT_MATCH);
return false;
}
// 查询用户权限是否有效:appid、appkey、uri
ApiUserUriMapping mapping = this.apiUserUriService.getApiUserUriMapping(appid, appkey, request.getRequestURI());
if (Objects.isNull(mapping)) {
reSetResponse(response, CommonEnum.NOT_PERMISSION);
return false;
}
}
request.setAttribute(TokenConstant.REQUEST_CURRENT_KEY, null);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
}
/**
* 登录拦截 重置响应数据
*
* @param response
*/
private void reSetResponse(HttpServletResponse response, CommonEnum commonEnum) {
PrintWriter pw = null;
try {
response.reset();
response.setContentType("application/json;charset=UTF-8");
ServiceResult serviceResult = new ServiceResult(commonEnum.getResultCode(), commonEnum.getResultMsg());
serviceResult.insertResult(null);
pw = response.getWriter();
pw.write(JSONObject.toJSONString(serviceResult));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (pw != null) {
pw.flush();
pw.close();
}
}
}
}
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
/**
* @author gk
* @note 配置类
* @date 2021/7/20 11:14
*/
@Configuration
public class WebConfigurer implements WebMvcConfigurer {
@Resource
private LoginInterceptor loginInterceptor;
//注册登录拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor).addPathPatterns("/**");//添加所需要拦截的接口,这里我们拦截所有,但是
// .excludePathPatterns("/**/evcs/v1/query_token/**"); //不拦截登陆和退出请求
}
//页面跳转
@Override
public void addViewControllers(ViewControllerRegistry registry) {
}
//配置静态资源
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
}
}
在接口方法上使用@AuthToken
该注解