裸奔的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") 这个需要加上,免得你代码出错再被拦截一次,还不知道哪里出错了
推荐阅读: