一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 淺談Java 三種方式實現接口校驗

淺談Java 三種方式實現接口校驗

2021-01-21 13:50BarryW Java教程

這篇文章主要介紹了淺談Java 三種方式實現接口校驗,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

本文介紹了Java 三種方式實現接口校驗,主要包括AOP,MVC攔截器,分享給大家,具體如下:

方法一:AOP

代碼如下定義一個權限注解

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.thinkgem.jeesite.common.annotation;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/**
 * 權限注解
 * Created by Hamming on 2016/12/
 */
@Target(ElementType.METHOD)//這個注解是應用在方法上
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessToken {
/*  String userId();
  String token();*/
}

獲取頁面請求中的ID token

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Aspect
@Component
public class AccessTokenAspect {
 
  @Autowired
  private ApiService apiService;
 
  @Around("@annotation(com.thinkgem.jeesite.common.annotation.AccessToken)")
  public Object doAccessCheck(ProceedingJoinPoint pjp) throws Throwable{
    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    String id = request.getParameter("id");
    String token = request.getParameter("token");
    boolean verify = apiService.verifyToken(id,token);
    if(verify){
      Object object = pjp.proceed(); //執行連接點方法
      //獲取執行方法的參數
 
      return object;
    }else {
      return ResultApp.error(3,"token失效");
    }
  }
}

token驗證類  存儲用到redis

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package com.thinkgem.jeesite.common.service;
 
import com.thinkgem.jeesite.common.utils.JedisUtils;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.crypto.MacProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import redis.clients.jedis.Jedis;
 
import java.io.*;
import java.security.Key;
import java.util.Date;
 
/**
 *token登陸驗證
 * Created by Hamming on 2016/12/
 */
@Service
public class ApiService {
  private static final String at="accessToken";
 
  public static Key key;
 
//  private Logger logger = LoggerFactorygetLogger(getClass());
  /**
   * 生成token
   * Key以字節流形式存入redis
   *
   * @param date 失效時間
   * @param appId AppId
   * @return
   */
  public String generateToken(Date date, String appId){
    Jedis jedis = null;
    try {
      jedis = JedisUtils.getResource();
      byte[] buf = jedis.get("api:key".getBytes());
      if (buf == null) { // 建新的key
        key = MacProvider.generateKey();
        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bao);
        oos.writeObject(key);
        buf = bao.toByteArray();
        jedis.set("api:key".getBytes(), buf);
      } else { // 重用老key
        key = (Key) new ObjectInputStream(new ByteArrayInputStream(buf)).readObject();
      }
 
    }catch (IOException io){
//      System.out.println(io);
    }catch (ClassNotFoundException c){
//      System.out.println(c);
    }catch (Exception e) {
//      logger.error("ApiService", "generateToken", key, e);
    } finally {
      JedisUtils.returnResource(jedis);
    }
 
    String token = Jwts.builder()
        .setSubject(appId)
        .signWith(SignatureAlgorithm.HS512, key)
        .setExpiration(date)
        .compact();
    // 計算失效秒,7889400秒三個月
    Date temp = new Date();
    long interval = (date.getTime() - temp.getTime())/1000;
    JedisUtils.set(at+appId ,token,(int)interval);
    return token;
  }
 
  /**
   * 驗證token
   * @param appId AppId
   * @param token token
   * @return
   */
  public boolean verifyToken(String appId, String token) {
    if( appId == null|| token == null){
      return false;
    }
    Jedis jedis = null;
    try {
      jedis = JedisUtils.getResource();
      if (key == null) {
        byte[] buf = jedis.get("api:key".getBytes());
        if(buf==null){
          return false;
        }
        key = (Key) new ObjectInputStream(new ByteArrayInputStream(buf))readObject();
      }
      Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody().getSubject().equals(appId);
      return true;
    } catch (Exception e) {
//      logger.error("ApiService", "verifyToken", key, e);
      return false;
    } finally {
      JedisUtils.returnResource(jedis);
    }
  }
 
  /**
   * 獲取token
   * @param appId
   * @return
   */
  public String getToken(String appId) {
    Jedis jedis = null;
    try {
      jedis = JedisUtils.getResource();
      return jedis.get(at+appId);
    } catch (Exception e) {
//      logger.error("ApiService", "getToken", e);
      return "";
    } finally {
      JedisUtils.returnResource(jedis);
    }
  }
}

spring aop配置

?
1
2
3
4
<!--aop -->
<!--   掃描注解bean -->
<context:component-scan base-package="com.thinkgem.jeesite.common.aspect"/>
 <aop:aspectj-autoproxy proxy-target-class="true"/>

驗證權限方法使用 直接用注解就可以了AccessToken

例如

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.thinkgem.jeesite.modules.app.web.pay;
 
import com.alibaba.fastjson.JSON;
import com.thinkgem.jeesite.common.annotation.AccessToken;
import com.thinkgem.jeesite.common.base.ResultApp;
import com.thinkgem.jeesite.modules.app.service.pay.AppAlipayConfService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
 
import java.util.HashMap;
import java.util.Map;
 
/**
 * 支付接口
 * Created by Hamming on 2016/12/
 */
@Controller
@RequestMapping(value = "/app/pay")
public class AppPayModule {
 
  @Autowired
  private AppAlipayConfService appAlipayConfService;
 
  @RequestMapping(value = "/alipay", method = RequestMethodPOST, produces="application/json")
  @AccessToken
  @ResponseBody
  public Object alipay(String orderId){
    if(orderId ==null){
      Map re = new HashMap<>();
      re.put("result",3);
      re.put("msg","參數錯誤");
      String json = JSONtoJSONString(re);
      return json;
    }else {
      return null;
    }
  }
}

方法二: AOP方法2

1.定義一個查詢父類,里面包含到authToken跟usedId兩個屬性,所有需要校驗用戶的請求的查詢參數都繼承這個查詢父類,之所以會有這個userId,是因為我們校驗得到用戶之后,需要根據用戶Id獲取一些用戶數據的,所以在AOP層我們就回填了這個參數了,這樣也不會影響之前的代碼邏輯(這個可能跟我的業務需求有關了)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class AuthSearchVO {
  
  public String authToken; //校驗字符串
  
  public Integer userId; //APP用戶Id
  
  public final String getAuthToken() {
    return authToken;
  }
 
  public final void setAuthToken(String authToken) {
    this.authToken = authToken;
  }
 
  public final Integer getUserId() {
    return userId;
  }
 
  public final void setUserId(Integer userId) {
    this.userId = userId;
  }
 
  @Override
  public String toString() {
    return "SearchVO [authToken=" + authToken + ", userId=" + userId + "]";
  }
 
}

2.定義一個方法級的注解,所有需要校驗的請求都加上這個注解,用于AOP的攔截(當然你也可以攔截所有控制器的請求)

?
1
2
3
4
5
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthToken {
String type();
}

3.AOP處理,之所以會將注解作為參數傳進來,是因為考慮到可能會有多個APP的校驗,可以利用注解的type屬性加以區分

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public class AuthTokenAOPInterceptor {
 
@Resource
private AppUserService appUserService;
 
private static final String authFieldName = "authToken";
private static final String userIdFieldName = "userId";
 
public void before(JoinPoint joinPoint, AuthToken authToken) throws Throwable{
 
  Object[] args = joinPoint.getArgs(); //獲取攔截方法的參數
  boolean isFound = false;
  for(Object arg : args){
    if(arg != null){
      Class<?> clazz = arg.getClass();//利用反射獲取屬性值
      Field[] fields = clazz.getDeclaredFields();
      int authIndex = -1;
      int userIdIndex = -1;
      for(int i = 0; i < fields.length; i++){
        Field field = fields[i];
        field.setAccessible(true);
        if(authFieldName.equals(field.getName())){//包含校驗Token
          authIndex = i;
        }else if(userIdFieldName.equals(field.getName())){//包含用戶Id
          userIdIndex = i;
        }
      }
 
      if(authIndex >= 0 & userIdIndex >= 0){
        isFound = true;
        authTokenCheck(fields[authIndex], fields[userIdIndex], arg, authToken);//校驗用戶
        break;
      }
    }
  }
  if(!isFound){
    throw new BizException(ErrorMessage.CHECK_AUTHTOKEN_FAIL);
  }
 
}
 
private void authTokenCheck(Field authField, Field userIdField, Object arg, AuthToken authToken) throws Exception{
  if(String.class == authField.getType()){
    String authTokenStr = (String)authField.get(arg);//獲取到校驗Token
    AppUser user = appUserService.getUserByAuthToken(authTokenStr);
    if(user != null){
      userIdField.set(arg, user.getId());
    }else{
      throw new BizException(ErrorMessage.CHECK_AUTHTOKEN_FAIL);
    }
  }
 
}
}

4.最后就是在配置文件中配置這個AOP了(因為我們的spring版本跟aspect版本有點出入,導致用不了基于注解的方式)

?
1
2
3
4
5
6
7
<bean id="authTokenAOPInterceptor" class="com.distinct.app.web.common.auth.AuthTokenAOPInterceptor"/>
<aop:config proxy-target-class="true">
  <aop:pointcut id="authCheckPointcut" expression="@annotation(authToken)"/>
  <aop:aspect ref="authTokenAOPInterceptor" order="1">
    <aop:before method="before" pointcut-ref="authCheckPointcut"/>
  </aop:aspect>
</aop:config>

最后給出測試代碼,這樣的代碼就優雅很多了

?
1
2
3
4
5
6
7
@RequestMapping(value = "/appointments", method = { RequestMethod.GET })
@ResponseBody
@AuthToken(type="disticntApp")
public List<AppointmentVo> getAppointments(AppointmentSearchVo appointmentSearchVo) {
  List<AppointmentVo> appointments = appointmentService.getAppointment(appointmentSearchVo.getUserId(), appointmentSearchVo);
  return appointments;
}

方法三: MVC攔截器

服務器:

拼接token之外所有參數,最后拼接token_key,做MD5,與token參數比對

如果token比對失敗返回狀態碼 500

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class APIInterceptor extends HandlerInterceptorAdapter {
 
  @Override
  public boolean preHandle(HttpServletRequest request,
      HttpServletResponse response, Object handler) throws Exception {
    Log.info(request);
     
    String token = request.getParameter("token");
     
    // token is not needed when debug
    if(token == null) return true; // !! remember to comment this when deploy on server !!
     
    Enumeration paraKeys = request.getParameterNames();
    String encodeStr = "";
    while (paraKeys.hasMoreElements()) {
      String paraKey = (String) paraKeys.nextElement();
      if(paraKey.equals("token")) 
        break;
      String paraValue = request.getParameter(paraKey);
      encodeStr += paraValue;
    }
    encodeStr += Default.TOKEN_KEY;
    Log.out(encodeStr);
     
    if ( ! token.equals(DigestUtils.md5Hex(encodeStr))) {
      response.setStatus(500);
      return false;
    }
     
    return true;
  }
 
  @Override
  public void postHandle(HttpServletRequest request,
      HttpServletResponse response, Object handler,
      ModelAndView modelAndView) throws Exception {
    Log.info(request);
  }
 
  @Override
  public void afterCompletion(HttpServletRequest request,
      HttpServletResponse response, Object handler, Exception ex)
      throws Exception {
     
  }
}

spring-config.xml配置中加入

?
1
2
3
4
5
6
<mvc:interceptors>
  <mvc:interceptor>
    <mvc:mapping path="/api/*" />
    <bean class="cn.web.interceptor.APIInterceptor" />
  </mvc:interceptor>
</mvc:interceptors>

客戶端:

拼接請求接口的所有參數,最后拼接token_key,做MD5,作為token參數

請求樣例:http://127.0.0.1:8080/interface/api?key0=param0&key1=param1&token=md5(concat(param0, param1))

api測試頁面,用到了Bootstrap和AngularJS,還有一個js的hex_md5函數

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<!doctype html>
<html ng-app>
<head>
  <meta charset="UTF-8">
  <title>API test</title>
  <link href="../css/bootstrap.min.css" rel="external nofollow" rel="stylesheet">
  <script src="../js/md5.min.js"></script>
  <script src="../js/angular.min.js"></script>
  <script>
    function API(url){
      this.url = arguments[0];
      this.params = Array.prototype.slice.call(arguments, 1, arguments.length);
      this.request = function(params){
        var addr = url;
        var values = Array.prototype.slice.call(arguments, 1, arguments.length);
        if(params[0] != undefined && values[0] != undefined && values[0] != '')
          addr += '?' + params[0] + "=" + values[0];
        for(var i=1; i < valueslength; i++)
          if(params[i] != undefined && values[i] != undefined && values[i] != '')
            addr += "&" + params[i] + "=" + values[i];
        return addr;
      }
    }
     
    function APIListCtrl($scope) {
      $scope.md5 = hex_md5;
      $scope.token_key = "9ae5r06fs8";
      $scope.concat = function(){
        var args = Array.prototype.slice.call(arguments, 0, arguments.length);
        args.push($scope.token_key);
        return args.join("");
      }
       
      $scope.apilist = [
       
      new API("account/login", "username", "pwd"),
      new API("account/register", "username", "pwd", "tel", "code"),
       
      ] ;
    }
  </script>
</head>
<body>
 
  <div ng-controller="APIListCtrl">
    <div> Search: <input type="text" ng-model="search"><hr>
    token_key <input type="text" ng-model="token_key">
    md5 <input type="text" ng-model="str"> {{md5(str)}}
    </div>
    <hr>
    <div ng-repeat="api in apilist | filter:search" >
      <form action="{{api.url}}" method="post">
      <a href="{{api.request(api.params, value0, value1, value2, value3, value4, value5, value6, value7, value8, value9)}}" rel="external nofollow" >
      {{api.request(api.params, value0, value1, value2, value3, value4, value5, value6, value7, value8, value9)}}
      </a>
      <br>
      {{concat(value0, value1, value2, value3, value4, value5, value6, value7, value8, value9)}}
      <br>
      {{api.params[0]}} <input id="{{api.params[0]}}" name="{{api.params[0]}}" ng-model="value0" ng-hide="api.params[0]==undefined">
      {{api.params[1]}} <input id="{{api.params[1]}}" name="{{api.params[1]}}" ng-model="value1" ng-hide="api.params[1]==undefined">
      {{api.params[2]}} <input id="{{api.params[2]}}" name="{{api.params[2]}}" ng-model="value2" ng-hide="api.params[2]==undefined">
      {{api.params[3]}} <input id="{{api.params[3]}}" name="{{api.params[3]}}" ng-model="value3" ng-hide="api.params[3]==undefined">
      {{api.params[4]}} <input id="{{api.params[4]}}" name="{{api.params[4]}}" ng-model="value4" ng-hide="api.params[4]==undefined">
      {{api.params[5]}} <input id="{{api.params[5]}}" name="{{api.params[5]}}" ng-model="value5" ng-hide="api.params[5]==undefined">
      {{api.params[6]}} <input id="{{api.params[6]}}" name="{{api.params[6]}}" ng-model="value6" ng-hide="api.params[6]==undefined">
      {{api.params[7]}} <input id="{{api.params[7]}}" name="{{api.params[7]}}" ng-model="value7" ng-hide="api.params[7]==undefined">
      {{api.params[8]}} <input id="{{api.params[8]}}" name="{{api.params[8]}}" ng-model="value8" ng-hide="api.params[8]==undefined">
      {{api.params[9]}} <input id="{{api.params[9]}}" name="{{api.params[9]}}" ng-model="value9" ng-hide="api.params[9]==undefined">
      token <input id="token" name="token" value="{{md5(concat(value0, value1, value2, value3, value4, value5, value6, value7, value8, value9))}}">
      <input type="submit" class="btn" ng-hide="api.params[0]==undefined">
      </form>
      <hr>
    </div>
  </div>
 
</body>
</html>

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.cnblogs.com/barrywxx/p/6964423.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产欧美日韩一区二区三区在线 | 果冻传媒第一二三专区 | 亚洲欧美国产精品完整版 | 国产在线观看精品香蕉v区 国产在线观看a | 国产香蕉97碰碰在线视频 | 97精品国产自在现线免费 | 99资源在线观看 | 2020年最新国产精品视频免费 | 狠狠色狠狠色综合曰曰 | 胸奶好大好紧好湿好爽 | 香蕉91视频| 91视频www| 皇上撞着太子妃的秘密小说 | yin乱被cao系列| 2021精品国夜夜天天拍拍 | 精品午夜中文字幕熟女人妻在线 | 精品久久香蕉国产线看观看麻豆 | 成年人在线视频免费观看 | 欧美日韩一区二区三区韩大 | 国产成人夜色91 | 国产精品亚洲综合久久 | 免费成年网 | 成人午夜影院在线观看 | 成人福利网 | 国内交换一区二区三区 | 精品国产乱码久久久人妻 | japan孕妇孕交freehd | 欧美日韩亚洲综合在线一区二区 | 欧美3p大片在线观看完整版 | 性欧美高清强烈性视频 | 天天综合天天影视色香欲俱全 | 60老妇性xxxxhd | 色综合网天天综合色中文男男 | 欧美sex另类孕妇 | 欧美乱子伦xxxx12在线 | 免费国产一级观看完整版 | 国产在线精品观看 | 好男人社区www影院在线观看 | 成人中文字幕在线观看 | 无限时间看片在线观看 | 福利片福利一区二区三区 |