java拦截器使用校验签名,拦截三方应用请求接口

1.通过实现HandlerInterceptor接口定义拦截器

package com.cnnho.redapplication.interceptor;

import com.alibaba.fastjson.JSON;
import com.cnnho.redapplication.config.ExternalPlatformConfig;
import com.cnnho.redcommon.entity.Response;
import com.cnnho.redcommon.util.AirUtils;
import com.cnnho.redcommon.util.CommonUtil;
import com.cnnho.redsystem.service.IAuthenticationService;
import com.cnnho.redsystem.service.impl.H5AuthenticationServiceImpl;
import com.cnnho.redsystem.service.impl.WebAuthenticationServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

import static com.cnnho.redcommon.util.CommonUtil.AUTH_TYPE.*;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

/***
* 请求拦截器
*/
@Slf4j
public class AuthenticationHandler implements HandlerInterceptor {

@Autowired
List<IAuthenticationService> authenticationServices;

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

String apiAuthKey = request.getHeader("Authentication");
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");

if(StringUtils.isEmpty(apiAuthKey) || apiAuthKey.length()<38) {
String msg = JSON.toJSONString(Response.error(Response.Type.NO_AUTH,null ));
response.getWriter().println(msg);
return false;
}

String type = apiAuthKey.substring(38,39);
log.debug("preHandle type is [{}]", type);
String authentication = apiAuthKey.substring(39, apiAuthKey.length());
log.debug("preHandle authentication is [{}]", authentication);

if(!MANAGE_TYPE.equals(type) && !FRONT_TYPE.equals(type) && !CARP_PRAISE.equals(type)) {
String msg = JSON.toJSONString(Response.error(Response.Type.TOKEN_ERROR,null ));
response.getWriter().println(msg);
return false;
}
IAuthenticationService server = null;
for(IAuthenticationService service : authenticationServices){
if(service.isSupport(type)) {
server = service;
break;
}
}

Response result = server.verifyAuthenticationForRedPacket(authentication);
if(AirUtils.hv(result)) {
String errInfo = JSON.toJSONString(result);
log.warn("preHandle failed info is [{}]", errInfo);
response.getWriter().println(errInfo);
return false;
}

if(CARP_PRAISE.equals(type)) {
log.debug("request请求地址path[{}] uri[{}]", request.getServletPath(), request.getRequestURI());
if (!ExternalPlatformConfig.isAllowedPathLZ(request.getServletPath())){
log.debug("理赞请求路径不合法,request请求地址path[{}] uri[{}]", request.getServletPath(), request.getRequestURI());
response.getWriter().println(Response.error(Response.Type.NO_AUTHORITY,null ));
return false;
}
}
log.debug("preHandle success token pass");
return true;
}
}



2.定义实现WebMvcConfigurationSupport的WebConfig配置类
package com.cnnho.redapplication.config;

import com.cnnho.redapplication.interceptor.AuthenticationHandler;
import org.springframework.context.annotation.Bean;
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.WebMvcConfigurationSupport;

/***
* 配置拦截器,验证token
*/
@Configuration
public class WebConfig extends WebMvcConfigurationSupport {

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations(
"classpath:/static/");
registry.addResourceHandler("swagger-ui.html").addResourceLocations(
"classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations(
"classpath:/META-INF/resources/webjars/");
super.addResourceHandlers(registry);
}

@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getAuthenticationHandler()).addPathPatterns("/user/**"

).excludePathPatterns("/user/login"
    }

@Bean
AuthenticationHandler getAuthenticationHandler(){
AuthenticationHandler handler = new AuthenticationHandler();
return handler;
}
}



3.校验token接口
package com.cnnho.redsystem.service;

import com.cnnho.redcommon.entity.Response;
import org.springframework.stereotype.Service;

/**
* @Description: TODO 获取Authentication接口
**/
@Service
public interface IAuthenticationService<T> {


/**
* @Description: TODO 生成Authentication签名
* @param userId 用户名
* @return
**/
public String getAuthenticationForRedPacket(T userId);


/**
*
* @Description: TODO 校验Authentication签名
* @param authentication 需校验的Authentication签名
* @return
**/
public Response verifyAuthenticationForRedPacket(String authentication);

/***
* service 标识
* @param type
* @return
*/
boolean isSupport(String type);

}



4.校验实现类(前端)
package com.cnnho.redsystem.service.impl;

import com.cnnho.redcommon.entity.Response;
import com.cnnho.redcommon.util.CommonUtil;
import com.cnnho.redcommon.util.JWTUtil;
import com.cnnho.redsystem.service.IAuthenticationService;
import com.cnnho.redsystem.service.cache.IRedPacketTokenCache;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.UUID;


/**
*
* @Description: 获取Authentication接口实现类(前端)
**/
@Slf4j
@Service
public class H5AuthenticationServiceImpl implements IAuthenticationService {

@Autowired
private IRedPacketTokenCache redPacketTokenCache;


/**
*
* @Description: 生成Authentication签名(前端)
* @param userId 用户名
* @return
**/
@Override
public String getAuthenticationForRedPacket(Object userId) {

//Authentication生成规则:CNNHO+32位UUID+"." + 1位标识符 + JWT编码后的数据 (标识符:1 后端登录用,2 前端接口用 3 鲤赞)
return "CNNHO"+ UUID.randomUUID().toString().replaceAll("-", "")+"."+ CommonUtil.AUTH_TYPE.FRONT_TYPE + JWTUtil.createToken((String)userId);
}

/**
*
* @Description: 校验Authentication签名(前端)
* @param authentication 需校验的Authentication签名
* @return
**/
@Override
public Response verifyAuthenticationForRedPacket(String authentication) {
if (StringUtils.isNotBlank(authentication)){

//1.解析authentication中的id(注:jwt已设置超时时间,不管是否超时,jwt签名中的信息都可被解析出来)
String id = JWTUtil.getId(authentication);
if (StringUtils.isNotBlank(id)){

//2.验证authentication是否正确(注:该方法会自动验证是否超时)
boolean b = JWTUtil.verify(authentication,id);
if (!b){
return Response.error(Response.Type.TOKEN_ERROR, null);
}

//3.若通过验证,则与缓存中存放的token进行比对
String apiAuthKey = redPacketTokenCache.getFrontAccessToken(id);
if(StringUtils.isEmpty(apiAuthKey)){
return Response.error(Response.Type.AUTH_FAILED, null);
}
String subToken = apiAuthKey.substring(39, apiAuthKey.length());
if (!authentication.equals(subToken)){
return Response.error(Response.Type.AUTH_FAILED, null);
}
}else {
return Response.error(Response.Type.NO_AUTH, null);

}
}
return null;
}

/***
* service 标识
* @param type
* @return
*/
@Override
public boolean isSupport(String type) {
return CommonUtil.AUTH_TYPE.FRONT_TYPE.equals(type);
}

}


5.校验token实现接口(后端)
package com.cnnho.redsystem.service.impl;

import com.cnnho.redcommon.entity.Response;
import com.cnnho.redcommon.util.CommonUtil;
import com.cnnho.redcommon.util.JWTUtil;
import com.cnnho.redsystem.service.IAuthenticationService;
import com.cnnho.redsystem.service.cache.IRedPacketTokenCache;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.UUID;


/**
*
* @Description: 获取Authentication接口实现类(后端)
**/
@Slf4j
@Service
public class WebAuthenticationServiceImpl implements IAuthenticationService {

@Autowired
private IRedPacketTokenCache redPacketTokenCache;


/**
*
* @Description: 生成Authentication签名(后端)
* @param userId 用户名
* @return
**/
@Override
public String getAuthenticationForRedPacket(Object userId) {

//Authentication生成规则:CNNHO+32位UUID+"." + 1位标识符 + JWT编码后的数据 (标识符:1 后端登录用,2 前端接口用 3 鲤赞)
return "CNNHO"+ UUID.randomUUID().toString().replaceAll("-", "")+"." + CommonUtil.AUTH_TYPE.MANAGE_TYPE + JWTUtil.createToken((String)userId);
}


/**
*
* @Description: 校验Authentication签名(后端)
* @param authentication 需校验的Authentication签名
* @return
**/
@Override
public Response verifyAuthenticationForRedPacket(String authentication) {
if (StringUtils.isNotBlank(authentication)){

//1.解析authentication中的id(注:jwt已设置超时时间,不管是否超时,jwt签名中的信息都可被解析出来)
String id = JWTUtil.getId(authentication);
if (StringUtils.isNotBlank(id)){

//2.验证authentication是否正确(注:该方法会自动验证是否超时)
boolean b = JWTUtil.verify(authentication,id);
if (!b){
return Response.error(Response.Type.TOKEN_ERROR, null);
}

//3.若通过验证,则与缓存中存放的token进行比对
String apiAuthKey = redPacketTokenCache.getManagerAccessToken(id);
if(StringUtils.isEmpty(apiAuthKey)){
return Response.error(Response.Type.AUTH_FAILED, null);
}
String subToken = apiAuthKey.substring(39, apiAuthKey.length());
if (!authentication.equals(subToken)){
return Response.error(Response.Type.AUTH_FAILED, null);
}
}else {
return Response.error(Response.Type.NO_AUTH, null);

}
}
return null;
}

/***
* service 标识
* @param type
* @return
*/
@Override
public boolean isSupport(String type) {
return CommonUtil.AUTH_TYPE.MANAGE_TYPE.equals(type);
}

}




6.拦截三方应用配置类
package com.cnnho.redapplication.config;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* @Description: 拦截三方应用配置
**/
@Slf4j
public final class ExternalPlatformConfig {
static final List<String> includePatterns = new ArrayList<>(Arrays.asList(
"/api/redPacket/theRestRedPacket",
"/api/redPacket/sendRedPacket",
"/api/redPacket/sendRedPacketByCode",
"/api/redPacket/getList",
"/api/redPacketDraw/winningInfo"
));

public static boolean isAllowedPathLZ(String path){
if (includePatterns.contains(path)){
return true;
}
return false;
}
}
原文地址:https://www.cnblogs.com/guangxiang/p/12529738.html