拦截器快速实现api鉴权,再也不用裸奔了

裸奔的api很多,裸奔习惯了也成自然了,不过冬天来了,还是不要裸奔,冷啊

此公众号大神太多,每天小编我都瑟瑟发抖,但是初学者更是主力,大神就自动略过了,高大上也会有,别着急,兄弟们多赚钱要紧哪

生成token的方式有两种:一种是通过加密算法生成一个有时效性的token,详见之前的代码,每一个代码都是有用的哦,互联网开发之神器:经典加解密函数Discuz authcode,然后header里带过来,进行解密,能够解密成功,代表数据是OK的

另外一种如oauth一般,存储与数据库然后有失效时间进行对比

显然第一种更节约成本

在springboot里进行api鉴权的方式有很多种,这里就介绍一种拦截器方式,直接上代码:

AuthenticationInterceptor:

package io.xxx.api.interceptor;


import com.alibaba.fastjson.JSON;
import io.xxx.api.annotation.ApiAuthentication;
import io.xxx.bitcoin.api.annotation.PassToken;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.DigestUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.Map;




public class AuthenticationInterceptor implements HandlerInterceptor {


    @Value("${xxx.inner_api_key}")
    private String inner_api_key;


    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
        String timestamp = httpServletRequest.getParameter("timestamp");
        String sign = httpServletRequest.getParameter("sign");
        if (!(object instanceof HandlerMethod)) {
            return true;
        } else {
            if (timestamp == null && sign == null) {
                BufferedReader streamReader = new BufferedReader(new InputStreamReader(httpServletRequest.getInputStream(), "UTF-8"));
                StringBuilder responseStrBuilder = new StringBuilder();
                String inputStr;
                while ((inputStr = streamReader.readLine()) != null) {
                    responseStrBuilder.append(inputStr);
                }
                try {
                    Map<String, String> map = JSON.parseObject(responseStrBuilder.toString(), Map.class);
                    timestamp = map.get("timestamp");
                    sign = map.get("sign");
                }catch (Exception e){
                    return false;
                    //throw new RuntimeException("param parse error,sign and timestamp cann't be null");
                }


            }


            HandlerMethod handlerMethod = (HandlerMethod) object;
            Method method = handlerMethod.getMethod();
            //检查是否有passtoken注释,有则跳过认证
            if (method.isAnnotationPresent(PassToken.class)) {
                PassToken passToken = method.getAnnotation(PassToken.class);
                if (passToken.required()) {
                    return true;
                }
            }
            if (method.isAnnotationPresent(ApiAuthentication.class)) {
                ApiAuthentication apiAuthentication = method.getAnnotation(ApiAuthentication.class);
                if (apiAuthentication.required()) {
                    if (sign == null || timestamp == null) {
                        throw new RuntimeException("sign and timestamp cann't be null");
                    }
                    String signStr = inner_api_key + timestamp;
                    String sign2 = DigestUtils.md5DigestAsHex(signStr.getBytes());
                    if (sign.equals(sign2) == false) {
                        throw new RuntimeException("签名错误");
                    }
                    return true;
                }
            }
        }


        return true;
    }


    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {


    }


    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {


    }
}


至于个人的鉴权认证方式,就自由发挥了,这里是一个简单的内部API调用鉴权,给APP 外部用的还是需要稍微复杂一些

GloablExceptionHandler:

@ControllerAdvice
public class GloablExceptionHandler {
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public Object handleException(Exception e) {
        String msg = e.getMessage();
        if (msg == null || msg.equals("")) {
            msg = "服务器出错";
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("message", msg);
        return jsonObject;
    }
}*/




InterceptorConfig:

package io.xxx.api.config;


import io.xxx.interceptor.AuthenticationInterceptor;
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.WebMvcConfigurer;




@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
         registry.addInterceptor(authenticationInterceptor())
        .addPathPatterns("/**");    // 拦截所有请求,通过判断是否有 @ApiAuthentication 注解 决定是否需要登录
       registration.excludePathPatterns("/error")
    }


    @Bean
    public AuthenticationInterceptor authenticationInterceptor() {
        return new AuthenticationInterceptor();
    }
}

registration.excludePathPatterns("/error") 这个需要加上,免得你代码出错再被拦截一次,还不知道哪里出错了

推荐阅读:

如何成为一个骚气的架构师,看这一篇就够了

亿级(无限级)并发,没那么难

从微盟删库事件血亏1.5亿,聊几点服务器安全

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值