• 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;
    }
    }
  • 相关阅读:
    在线程中使用OpenFileDialog
    Log4net附加
    SQL表间列根据条件复制(赋值)
    DataGridView使用
    Latex使用总结及备忘
    Windows获取文件状态
    TabControl取消首次定位焦点
    C#跨线程调用
    电子词典的查寻程序,发送和接收应答程序
    电子词典的相关子函数db.c程序
  • 原文地址:https://www.cnblogs.com/guangxiang/p/12529738.html
Copyright © 2020-2023  润新知