国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

API 面試四連殺:接口如何設(shè)計(jì)?安全如何保證?簽名如何實(shí)現(xiàn)?防重如何實(shí)現(xiàn)?

共 7408字,需瀏覽 15分鐘

 ·

2021-02-21 07:25


下面我們就來討論下常用的一些API設(shè)計(jì)的安全方法,可能不一定是最好的,有更牛逼的實(shí)現(xiàn)方式,但是這篇是我自己的經(jīng)驗(yàn)分享.

一、token 簡(jiǎn)介

Token:訪問令牌access token, 用于接口中, 用于標(biāo)識(shí)接口調(diào)用者的身份、憑證,減少用戶名和密碼的傳輸次數(shù)。一般情況下客戶端(接口調(diào)用方)需要先向服務(wù)器端申請(qǐng)一個(gè)接口調(diào)用的賬號(hào),服務(wù)器會(huì)給出一個(gè)appId和一個(gè)key, key用于參數(shù)簽名使用,注意key保存到客戶端,需要做一些安全處理,防止泄露。

Token的值一般是UUID,服務(wù)端生成Token后需要將token做為key,將一些和token關(guān)聯(lián)的信息作為value保存到緩存服務(wù)器中(redis),當(dāng)一個(gè)請(qǐng)求過來后,服務(wù)器就去緩存服務(wù)器中查詢這個(gè)Token是否存在,存在則調(diào)用接口,不存在返回接口錯(cuò)誤,一般通過攔截器或者過濾器來實(shí)現(xiàn),Token分為兩種:

  • API Token(接口令牌): 用于訪問不需要用戶登錄的接口,如登錄、注冊(cè)、一些基本數(shù)據(jù)的獲取等。獲取接口令牌需要拿appId、timestamp和sign來換,sign=加密(timestamp+key)
  • USER Token(用戶令牌): 用于訪問需要用戶登錄之后的接口,如:獲取我的基本信息、保存、修改、刪除等操作。獲取用戶令牌需要拿用戶名和密碼來換

關(guān)于Token的時(shí)效性:token可以是一次性的、也可以在一段時(shí)間范圍內(nèi)是有效的,具體使用哪種看業(yè)務(wù)需要。

一般情況下接口最好使用https協(xié)議,如果使用http協(xié)議,Token機(jī)制只是一種減少被黑的可能性,其實(shí)只能防君子不能防小人。

一般token、timestamp和sign 三個(gè)參數(shù)會(huì)在接口中會(huì)同時(shí)作為參數(shù)傳遞,每個(gè)參數(shù)都有各自的用途。

二、timestamp 簡(jiǎn)介

timestamp: 時(shí)間戳,是客戶端調(diào)用接口時(shí)對(duì)應(yīng)的當(dāng)前時(shí)間戳,時(shí)間戳用于防止DoS攻擊。當(dāng)黑客劫持了請(qǐng)求的url去DoS攻擊,每次調(diào)用接口時(shí)接口都會(huì)判斷服務(wù)器當(dāng)前系統(tǒng)時(shí)間和接口中傳的的timestamp的差值,如果這個(gè)差值超過某個(gè)設(shè)置的時(shí)間(假如5分鐘),那么這個(gè)請(qǐng)求將被攔截掉,如果在設(shè)置的超時(shí)時(shí)間范圍內(nèi),是不能阻止DoS攻擊的。timestamp機(jī)制只能減輕DoS攻擊的時(shí)間,縮短攻擊時(shí)間。如果黑客修改了時(shí)間戳的值可通過sign簽名機(jī)制來處理。

DoS

DoS是Denial of Service的簡(jiǎn)稱,即拒絕服務(wù),造成DoS的攻擊行為被稱為DoS攻擊,其目的是使計(jì)算機(jī)或網(wǎng)絡(luò)無法提供正常的服務(wù)。最常見的DoS攻擊有計(jì)算機(jī)網(wǎng)絡(luò)帶寬攻擊和連通性攻擊。

DoS攻擊是指故意的攻擊網(wǎng)絡(luò)協(xié)議實(shí)現(xiàn)的缺陷或直接通過野蠻手段殘忍地耗盡被攻擊對(duì)象的資源,目的是讓目標(biāo)計(jì)算機(jī)或網(wǎng)絡(luò)無法提供正常的服務(wù)或資源訪問,使目標(biāo)系統(tǒng)服務(wù)系統(tǒng)停止響應(yīng)甚至崩潰,而在此攻擊中并不包括侵入目標(biāo)服務(wù)器或目標(biāo)網(wǎng)絡(luò)設(shè)備。這些服務(wù)資源包括網(wǎng)絡(luò)帶寬,文件系統(tǒng)空間容量,開放的進(jìn)程或者允許的連接。這種攻擊會(huì)導(dǎo)致資源的匱乏,無論計(jì)算機(jī)的處理速度多快、內(nèi)存容量多大、網(wǎng)絡(luò)帶寬的速度多快都無法避免這種攻擊帶來的后果。

  • Pingflood: 該攻擊在短時(shí)間內(nèi)向目的主機(jī)發(fā)送大量ping包,造成網(wǎng)絡(luò)堵塞或主機(jī)資源耗盡。

  • Synflood: 該攻擊以多個(gè)隨機(jī)的源主機(jī)地址向目的主機(jī)發(fā)送SYN包,而在收到目的主機(jī)的SYN ACK后并不回應(yīng),這樣,目的主機(jī)就為這些源主機(jī)建立了大量的連接隊(duì)列,而且由于沒有收到ACK一直維護(hù)著這些隊(duì)列,造成了資源的大量消耗而不能向正常請(qǐng)求提供服務(wù)。

  • Smurf:該攻擊向一個(gè)子網(wǎng)的廣播地址發(fā)一個(gè)帶有特定請(qǐng)求(如ICMP回應(yīng)請(qǐng)求)的包,并且將源地址偽裝成想要攻擊的主機(jī)地址。子網(wǎng)上所有主機(jī)都回應(yīng)廣播包請(qǐng)求而向被攻擊主機(jī)發(fā)包,使該主機(jī)受到攻擊。

  • Land-based:攻擊者將一個(gè)包的源地址和目的地址都設(shè)置為目標(biāo)主機(jī)的地址,然后將該包通過IP欺騙的方式發(fā)送給被攻擊主機(jī),這種包可以造成被攻擊主機(jī)因試圖與自己建立連接而陷入死循環(huán),從而很大程度地降低了系統(tǒng)性能。

  • Ping of Death:根據(jù)TCP/IP的規(guī)范,一個(gè)包的長(zhǎng)度最大為65536字節(jié)。盡管一個(gè)包的長(zhǎng)度不能超過65536字節(jié),但是一個(gè)包分成的多個(gè)片段的疊加卻能做到。當(dāng)一個(gè)主機(jī)收到了長(zhǎng)度大于65536字節(jié)的包時(shí),就是受到了Ping of Death攻擊,該攻擊會(huì)造成主機(jī)的宕機(jī)。

  • Teardrop:IP數(shù)據(jù)包在網(wǎng)絡(luò)傳遞時(shí),數(shù)據(jù)包可以分成更小的片段。攻擊者可以通過發(fā)送兩段(或者更多)數(shù)據(jù)包來實(shí)現(xiàn)TearDrop攻擊。第一個(gè)包的偏移量為0,長(zhǎng)度為N,第二個(gè)包的偏移量小于N。為了合并這些數(shù)據(jù)段,TCP/IP堆棧會(huì)分配超乎尋常的巨大資源,從而造成系統(tǒng)資源的缺乏甚至機(jī)器的重新啟動(dòng)。

  • PingSweep:使用ICMP Echo輪詢多個(gè)主機(jī)。

三、sign 簡(jiǎn)介

nonce:隨機(jī)值,是客戶端隨機(jī)生成的值,作為參數(shù)傳遞過來,隨機(jī)值的目的是增加sign簽名的多變性。隨機(jī)值一般是數(shù)字和字母的組合,6位長(zhǎng)度,隨機(jī)值的組成和長(zhǎng)度沒有固定規(guī)則。

sign: 一般用于參數(shù)簽名,防止參數(shù)被非法篡改,最常見的是修改金額等重要敏感參數(shù), sign的值一般是將所有非空參數(shù)按照升續(xù)排序然后+token+key+timestamp+nonce(隨機(jī)數(shù))拼接在一起,然后使用某種加密算法進(jìn)行加密,作為接口中的一個(gè)參數(shù)sign來傳遞,也可以將sign放到請(qǐng)求頭中。接口在網(wǎng)絡(luò)傳輸過程中如果被黑客挾持,并修改其中的參數(shù)值,然后再繼續(xù)調(diào)用接口,雖然參數(shù)的值被修改了,但是因?yàn)楹诳筒恢纒ign是如何計(jì)算出來的,不知道sign都有哪些值構(gòu)成,不知道以怎樣的順序拼接在一起的,最重要的是不知道簽名字符串中的key是什么,所以黑客可以篡改參數(shù)的值,但沒法修改sign的值,當(dāng)服務(wù)器調(diào)用接口前會(huì)按照sign的規(guī)則重新計(jì)算出sign的值然后和接口傳遞的sign參數(shù)的值做比較,如果相等表示參數(shù)值沒有被篡改,如果不等,表示參數(shù)被非法篡改了,就不執(zhí)行接口了。

四、防止重復(fù)提交

對(duì)于一些重要的操作需要防止客戶端重復(fù)提交的(如非冪等性重要操作),具體辦法是當(dāng)請(qǐng)求第一次提交時(shí)將sign作為key保存到redis,并設(shè)置超時(shí)時(shí)間,超時(shí)時(shí)間和Timestamp中設(shè)置的差值相同。當(dāng)同一個(gè)請(qǐng)求第二次訪問時(shí)會(huì)先檢測(cè)redis是否存在該sign,如果存在則證明重復(fù)提交了,接口就不再繼續(xù)調(diào)用了。如果sign在緩存服務(wù)器中因過期時(shí)間到了,而被刪除了,此時(shí)當(dāng)這個(gè)url再次請(qǐng)求服務(wù)器時(shí),因token的過期時(shí)間和sign的過期時(shí)間一直,sign過期也意味著token過期,那樣同樣的url再訪問服務(wù)器會(huì)因token錯(cuò)誤會(huì)被攔截掉,這就是為什么sign和token的過期時(shí)間要保持一致的原因。拒絕重復(fù)調(diào)用機(jī)制確保URL被別人截獲了也無法使用(如抓取數(shù)據(jù))。

對(duì)于哪些接口需要防止重復(fù)提交可以自定義個(gè)注解來標(biāo)記。

注意:所有的安全措施都用上的話有時(shí)候難免太過復(fù)雜,在實(shí)際項(xiàng)目中需要根據(jù)自身情況作出裁剪,比如可以只使用簽名機(jī)制就可以保證信息不會(huì)被篡改,或者定向提供服務(wù)的時(shí)候只用Token機(jī)制就可以了。如何裁剪,全看項(xiàng)目實(shí)際情況和對(duì)接口安全性的要求。

五、使用流程

  1. 接口調(diào)用方(客戶端)向接口提供方(服務(wù)器)申請(qǐng)接口調(diào)用賬號(hào),申請(qǐng)成功后,接口提供方會(huì)給接口調(diào)用方一個(gè)appId和一個(gè)key參數(shù)
  2. 客戶端攜帶參數(shù)appId、timestamp、sign去調(diào)用服務(wù)器端的API token,其中sign=加密(appId + timestamp + key)
  3. 客戶端拿著api_token 去訪問不需要登錄就能訪問的接口
  4. 當(dāng)訪問用戶需要登錄的接口時(shí),客戶端跳轉(zhuǎn)到登錄頁面,通過用戶名和密碼調(diào)用登錄接口,登錄接口會(huì)返回一個(gè)usertoken, 客戶端拿著usertoken 去訪問需要登錄才能訪問的接口

sign的作用是防止參數(shù)被篡改,客戶端調(diào)用服務(wù)端時(shí)需要傳遞sign參數(shù),服務(wù)器響應(yīng)客戶端時(shí)也可以返回一個(gè)sign用于客戶度校驗(yàn)返回的值是否被非法篡改了。客戶端傳的sign和服務(wù)器端響應(yīng)的sign算法可能會(huì)不同。

六、示例代碼

1. dependency

<dependency>
????<groupId>org.springframework.bootgroupId>
????<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
????<groupId>redis.clientsgroupId>
????<artifactId>jedisartifactId>
????<version>2.9.0version>
dependency>

<dependency>
????<groupId>org.springframework.bootgroupId>
????<artifactId>spring-boot-starter-webartifactId>
dependency>

2. RedisConfiguration

@Configuration
public?class?RedisConfiguration?{
????@Bean
????public?JedisConnectionFactory?jedisConnectionFactory(){
????????return?new?JedisConnectionFactory();
????}

????/**
?????*?支持存儲(chǔ)對(duì)象
?????*?@return
?????*/

????@Bean
????public?RedisTemplate?redisTemplate(){
????????RedisTemplate?redisTemplate?=?new?StringRedisTemplate();
????????redisTemplate.setConnectionFactory(jedisConnectionFactory());
????????Jackson2JsonRedisSerializer?jackson2JsonRedisSerializer?=?new?Jackson2JsonRedisSerializer(Object.class);
????????ObjectMapper?objectMapper?=?new?ObjectMapper();
????????objectMapper.setVisibility(PropertyAccessor.ALL,?JsonAutoDetect.Visibility.ANY);
????????objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

????????jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
????????redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
????????redisTemplate.afterPropertiesSet();

????????return?redisTemplate;
????}
}

3. TokenController

@Slf4j
@RestController
@RequestMapping("/api/token")
public?class?TokenController?{

????@Autowired
????private?RedisTemplate?redisTemplate;

????/**
?????*?API?Token
?????*
?????*?@param?sign
?????*?@return
?????*/

????@PostMapping("/api_token")
????public?ApiResponse?apiToken(String?appId,?@RequestHeader("timestamp")?String?timestamp,?@RequestHeader("sign")?String?sign)?{
????????Assert.isTrue(!StringUtils.isEmpty(appId)?&&?!StringUtils.isEmpty(timestamp)?&&?!StringUtils.isEmpty(sign),?"參數(shù)錯(cuò)誤");

????????long?reqeustInterval?=?System.currentTimeMillis()?-?Long.valueOf(timestamp);
????????Assert.isTrue(reqeustInterval?5?*?60?*?1000,?"請(qǐng)求過期,請(qǐng)重新請(qǐng)求");

????????//?1.?根據(jù)appId查詢數(shù)據(jù)庫(kù)獲取appSecret
????????AppInfo?appInfo?=?new?AppInfo("1",?"12345678954556");

????????//?2.?校驗(yàn)簽名
????????String?signString?=?timestamp?+?appId?+?appInfo.getKey();
????????String?signature?=?MD5Util.encode(signString);
????????log.info(signature);
????????Assert.isTrue(signature.equals(sign),?"簽名錯(cuò)誤");

????????//?3.?如果正確生成一個(gè)token保存到redis中,如果錯(cuò)誤返回錯(cuò)誤信息
????????AccessToken?accessToken?=?this.saveToken(0,?appInfo,?null);

????????return?ApiResponse.success(accessToken);
????}


????@NotRepeatSubmit(5000)
????@PostMapping("user_token")
????public?ApiResponse?userToken(String?username,?String?password)?{
????????//?根據(jù)用戶名查詢密碼,?并比較密碼(密碼可以RSA加密一下)
????????UserInfo?userInfo?=?new?UserInfo(username,?"81255cb0dca1a5f304328a70ac85dcbd",?"111111");
????????String?pwd?=?password?+?userInfo.getSalt();
????????String?passwordMD5?=?MD5Util.encode(pwd);
????????Assert.isTrue(passwordMD5.equals(userInfo.getPassword()),?"密碼錯(cuò)誤");

????????//?2.?保存Token
????????AppInfo?appInfo?=?new?AppInfo("1",?"12345678954556");
????????AccessToken?accessToken?=?this.saveToken(1,?appInfo,?userInfo);
????????userInfo.setAccessToken(accessToken);
????????return?ApiResponse.success(userInfo);
????}

????private?AccessToken?saveToken(int?tokenType,?AppInfo?appInfo,??UserInfo?userInfo)?{
????????String?token?=?UUID.randomUUID().toString();

????????//?token有效期為2小時(shí)
????????Calendar?calendar?=?Calendar.getInstance();
????????calendar.setTime(new?Date());
????????calendar.add(Calendar.SECOND,?7200);
????????Date?expireTime?=?calendar.getTime();

????????//?4.?保存token
????????ValueOperations?operations?=?redisTemplate.opsForValue();
????????TokenInfo?tokenInfo?=?new?TokenInfo();
????????tokenInfo.setTokenType(tokenType);
????????tokenInfo.setAppInfo(appInfo);

????????if?(tokenType?==?1)?{
????????????tokenInfo.setUserInfo(userInfo);
????????}

????????operations.set(token,?tokenInfo,?7200,?TimeUnit.SECONDS);

????????AccessToken?accessToken?=?new?AccessToken(token,?expireTime);

????????return?accessToken;
????}

????public?static?void?main(String[]?args)?{
????????long?timestamp?=?System.currentTimeMillis();
????????System.out.println(timestamp);
????????String?signString?=?timestamp?+?"1"?+?"12345678954556";
????????String?sign?=?MD5Util.encode(signString);
????????System.out.println(sign);

????????System.out.println("-------------------");
????????signString?=?"password=123456&username=1&12345678954556"?+?"ff03e64b-427b-45a7-b78b-47d9e8597d3b1529815393153sdfsdfsfs"?+?timestamp?+?"A1scr6";
????????sign?=?MD5Util.encode(signString);
????????System.out.println(sign);
????}
}

4. WebMvcConfiguration

@Configuration
public?class?WebMvcConfiguration?extends?WebMvcConfigurationSupport?{

????private?static?final?String[]?excludePathPatterns??=?{"/api/token/api_token"};

????@Autowired
????private?TokenInterceptor?tokenInterceptor;

????@Override
????public?void?addInterceptors(InterceptorRegistry?registry)?{
????????super.addInterceptors(registry);
????????registry.addInterceptor(tokenInterceptor)
????????????????.addPathPatterns("/api/**")
????????????????.excludePathPatterns(excludePathPatterns);
????}
}

5. TokenInterceptor

@Component
public?class?TokenInterceptor?extends?HandlerInterceptorAdapter?{

????@Autowired
????private?RedisTemplate?redisTemplate;

????/**
?????*
?????*?@param?request
?????*?@param?response
?????*?@param?handler?訪問的目標(biāo)方法
?????*?@return
?????*?@throws?Exception
?????*/

????@Override
????public?boolean?preHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler)?throws?Exception?{
????????String?token?=?request.getHeader("token");
????????String?timestamp?=?request.getHeader("timestamp");
????????//?隨機(jī)字符串
????????String?nonce?=?request.getHeader("nonce");
????????String?sign?=?request.getHeader("sign");
????????Assert.isTrue(!StringUtils.isEmpty(token)?&&?!StringUtils.isEmpty(timestamp)?&&?!StringUtils.isEmpty(sign),?"參數(shù)錯(cuò)誤");

????????//?獲取超時(shí)時(shí)間
????????NotRepeatSubmit?notRepeatSubmit?=?ApiUtil.getNotRepeatSubmit(handler);
????????long?expireTime?=?notRepeatSubmit?==?null???5?*?60?*?1000?:?notRepeatSubmit.value();

????????//?2.?請(qǐng)求時(shí)間間隔
????????long?reqeustInterval?=?System.currentTimeMillis()?-?Long.valueOf(timestamp);
????????Assert.isTrue(reqeustInterval?"請(qǐng)求超時(shí),請(qǐng)重新請(qǐng)求");

????????//?3.?校驗(yàn)Token是否存在
????????ValueOperations?tokenRedis?=?redisTemplate.opsForValue();
????????TokenInfo?tokenInfo?=?tokenRedis.get(token);
????????Assert.notNull(tokenInfo,?"token錯(cuò)誤");

????????//?4.?校驗(yàn)簽名(將所有的參數(shù)加進(jìn)來,防止別人篡改參數(shù))?所有參數(shù)看參數(shù)名升續(xù)排序拼接成url
????????//?請(qǐng)求參數(shù)?+?token?+?timestamp?+?nonce
????????String?signString?=?ApiUtil.concatSignString(request)?+?tokenInfo.getAppInfo().getKey()?+?token?+?timestamp?+?nonce;
????????String?signature?=?MD5Util.encode(signString);
????????boolean?flag?=?signature.equals(sign);
????????Assert.isTrue(flag,?"簽名錯(cuò)誤");

????????//?5.?拒絕重復(fù)調(diào)用(第一次訪問時(shí)存儲(chǔ),過期時(shí)間和請(qǐng)求超時(shí)時(shí)間保持一致),?只有標(biāo)注不允許重復(fù)提交注解的才會(huì)校驗(yàn)
????????if?(notRepeatSubmit?!=?null)?{
????????????ValueOperations?signRedis?=?redisTemplate.opsForValue();
????????????boolean?exists?=?redisTemplate.hasKey(sign);
????????????Assert.isTrue(!exists,?"請(qǐng)勿重復(fù)提交");
????????????signRedis.set(sign,?0,?expireTime,?TimeUnit.MILLISECONDS);
????????}

????????return?super.preHandle(request,?response,?handler);
????}
}

6. MD5Util ----MD5工具類,加密生成數(shù)字簽名

public?class?MD5Util?{

????private?static?final?String?hexDigits[]?=?{?"0",?"1",?"2",?"3",?"4",?"5",
????????????"6",?"7",?"8",?"9",?"a",?"b",?"c",?"d",?"e",?"f"?};

????private?static?String?byteArrayToHexString(byte?b[])?{
????????StringBuffer?resultSb?=?new?StringBuffer();
????????for?(int?i?=?0;?i?????????????resultSb.append(byteToHexString(b[i]));

????????return?resultSb.toString();
????}

????private?static?String?byteToHexString(byte?b)?{
????????int?n?=?b;
????????if?(n?0)
????????????n?+=?256;
????????int?d1?=?n?/?16;
????????int?d2?=?n?%?16;
????????return?hexDigits[d1]?+?hexDigits[d2];
????}

????public?static?String?encode(String?origin)?{
????????return?encode(origin,?"UTF-8");
????}
????public?static?String?encode(String?origin,?String?charsetname)?{
????????String?resultString?=?null;
????????try?{
????????????resultString?=?new?String(origin);
????????????MessageDigest?md?=?MessageDigest.getInstance("MD5");
????????????if?(charsetname?==?null?||?"".equals(charsetname))
????????????????resultString?=?byteArrayToHexString(md.digest(resultString
????????????????????????.getBytes()));
????????????else
????????????????resultString?=?byteArrayToHexString(md.digest(resultString
????????????????????????.getBytes(charsetname)));
????????}?catch?(Exception?exception)?{
????????}
????????return?resultString;
????}
}

7. @NotRepeatSubmit ?-----自定義注解,防止重復(fù)提交。

/**
?*?禁止重復(fù)提交
?*/

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public?@interface?NotRepeatSubmit?{
????/**?過期時(shí)間,單位毫秒?**/
????long?value()?default?5000;
}?

8. AccessToken

@Data
@AllArgsConstructor
public?class?AccessToken?{
????/**?token?*/
????private?String?token;

????/**?失效時(shí)間?*/
????private?Date?expireTime;
}

9. AppInfo

@Data
@NoArgsConstructor
@AllArgsConstructor
public?class?AppInfo?{
????/**?App?id?*/
????private?String?appId;
????/**?API?秘鑰?*/
????private?String?key;
}

10. TokenInfo

@Data
public?class?TokenInfo?{
????/**?token類型:?api:0?、user:1?*/
????private?Integer?tokenType;

????/**?App?信息?*/
????private?AppInfo?appInfo;

????/**?用戶其他數(shù)據(jù)?*/
????private?UserInfo?userInfo;
}

11. UserInfo

@Data
public?class?UserInfo?{
????/**?用戶名?*/
????private?String?username;
????/**?手機(jī)號(hào)?*/
????private?String?mobile;
????/**?郵箱?*/
????private?String?email;
????/**?密碼?*/
????private?String?password;
????/**?鹽?*/
????private?String?salt;

????private?AccessToken?accessToken;

????public?UserInfo(String?username,?String?password,?String?salt)?{
????????this.username?=?username;
????????this.password?=?password;
????????this.salt?=?salt;
????}
}

12. ApiCodeEnum

/**
?*?錯(cuò)誤碼code可以使用純數(shù)字,使用不同區(qū)間標(biāo)識(shí)一類錯(cuò)誤,也可以使用純字符,也可以使用前綴+編號(hào)
?*
?*?錯(cuò)誤碼:ERR +?編號(hào)
?*
?*?可以使用日志級(jí)別的前綴作為錯(cuò)誤類型區(qū)分?Info(I)?Error(E)?Warning(W)
?*
?*?或者以業(yè)務(wù)模塊?+?錯(cuò)誤號(hào)
?*
?*?TODO?錯(cuò)誤碼設(shè)計(jì)
?*
?*?Alipay?用了兩個(gè)code,兩個(gè)msg(https://docs.open.alipay.com/api_1/alipay.trade.pay)
?*/

public?enum?ApiCodeEnum?{
????SUCCESS("10000",?"success"),
????UNKNOW_ERROR("ERR0001","未知錯(cuò)誤"),
????PARAMETER_ERROR("ERR0002","參數(shù)錯(cuò)誤"),
????TOKEN_EXPIRE("ERR0003","認(rèn)證過期"),
????REQUEST_TIMEOUT("ERR0004","請(qǐng)求超時(shí)"),
????SIGN_ERROR("ERR0005","簽名錯(cuò)誤"),
????REPEAT_SUBMIT("ERR0006","請(qǐng)不要頻繁操作"),
????;

????/**?代碼?*/
????private?String?code;

????/**?結(jié)果?*/
????private?String?msg;

????ApiCodeEnum(String?code,?String?msg)?{
????????this.code?=?code;
????????this.msg?=?msg;
????}

????public?String?getCode()?{
????????return?code;
????}

????public?String?getMsg()?{
????????return?msg;
????}
}?

13. ApiResult

@Data
@NoArgsConstructor
@AllArgsConstructor
public?class?ApiResult?{

????/**?代碼?*/
????private?String?code;

????/**?結(jié)果?*/
????private?String?msg;
}

14. ApiUtil -------這個(gè)參考支付寶加密的算法寫的.我直接Copy過來了。

public?class?ApiUtil?{

????/**
?????*?按參數(shù)名升續(xù)拼接參數(shù)
?????*?@param?request
?????*?@return
?????*/

????public?static?String?concatSignString(HttpServletRequest?request)?{
????????Map?paramterMap?=?new?HashMap<>();
????????request.getParameterMap().forEach((key,?value)?->?paramterMap.put(key,?value[0]));
????????//?按照key升續(xù)排序,然后拼接參數(shù)
????????Set?keySet?=?paramterMap.keySet();
????????String[]?keyArray?=?keySet.toArray(new?String[keySet.size()]);
????????Arrays.sort(keyArray);
????????StringBuilder?sb?=?new?StringBuilder();
????????for?(String?k?:?keyArray)?{
????????????//?或略掉的字段
????????????if?(k.equals("sign"))?{
????????????????continue;
????????????}
????????????if?(paramterMap.get(k).trim().length()?>?0)?{
????????????????//?參數(shù)值為空,則不參與簽名
????????????????sb.append(k).append("=").append(paramterMap.get(k).trim()).append("&");
????????????}
????????}

????????return?sb.toString();
????}

????public?static?String?concatSignString(Map?map)?{
????????Map?paramterMap?=?new?HashMap<>();
????????map.forEach((key,?value)?->?paramterMap.put(key,?value));
????????//?按照key升續(xù)排序,然后拼接參數(shù)
????????Set?keySet?=?paramterMap.keySet();
????????String[]?keyArray?=?keySet.toArray(new?String[keySet.size()]);
????????Arrays.sort(keyArray);
????????StringBuilder?sb?=?new?StringBuilder();
????????for?(String?k?:?keyArray)?{
????????????if?(paramterMap.get(k).trim().length()?>?0)?{
????????????????//?參數(shù)值為空,則不參與簽名
????????????????sb.append(k).append("=").append(paramterMap.get(k).trim()).append("&");
????????????}
????????}
????????return?sb.toString();
????}

????/**
?????*?獲取方法上的@NotRepeatSubmit注解
?????*?@param?handler
?????*?@return
?????*/

????public?static?NotRepeatSubmit?getNotRepeatSubmit(Object?handler)?{
????????if?(handler?instanceof?HandlerMethod)?{
????????????HandlerMethod?handlerMethod?=?(HandlerMethod)?handler;
????????????Method?method?=?handlerMethod.getMethod();
????????????NotRepeatSubmit?annotation?=?method.getAnnotation(NotRepeatSubmit.class);

????????????return?annotation;
????????}

????????return?null;
????}
}

15. ApiResponse

@Data
@Slf4j
public?class?ApiResponse<T>?{
????/**?結(jié)果?*/
????private?ApiResult?result;

????/**?數(shù)據(jù)?*/
????private?T?data;

????/**?簽名?*/
????private?String?sign;


????public?static??ApiResponse?success(T?data)?{
????????return?response(ApiCodeEnum.SUCCESS.getCode(),?ApiCodeEnum.SUCCESS.getMsg(),?data);
????}

????public?static?ApiResponse?error(String?code,?String?msg)?{
????????return?response(code,?msg,?null);
????}

????public?static??ApiResponse?response(String?code,?String?msg,?T?data)?{
????????ApiResult?result?=?new?ApiResult(code,?msg);
????????ApiResponse?response?=?new?ApiResponse();
????????response.setResult(result);
????????response.setData(data);

????????String?sign?=?signData(data);
????????response.setSign(sign);

????????return?response;
????}

????private?static??String?signData(T?data)?{
????????//?TODO?查詢key
????????String?key?=?"12345678954556";
????????Map?responseMap?=?null;
????????try?{
????????????responseMap?=?getFields(data);
????????}?catch?(IllegalAccessException?e)?{
????????????return?null;
????????}
????????String?urlComponent?=?ApiUtil.concatSignString(responseMap);
????????String?signature?=?urlComponent?+?"key="?+?key;
????????String?sign?=?MD5Util.encode(signature);

????????return?sign;
????}

????/**
?????*?@param?data?反射的對(duì)象,獲取對(duì)象的字段名和值
?????*?@throws?IllegalArgumentException
?????*?@throws?IllegalAccessException
?????*/

????public?static?Map?getFields(Object?data)?throws?IllegalAccessException,?IllegalArgumentException?{
????????if?(data?==?null)?return?null;
????????Map?map?=?new?HashMap<>();
????????Field[]?fields?=?data.getClass().getDeclaredFields();
????????for?(int?i?=?0;?i?????????????Field?field?=?fields[i];
????????????field.setAccessible(true);

????????????String?name?=?field.getName();
????????????Object?value?=?field.get(data);
????????????if?(field.get(data)?!=?null)?{
????????????????map.put(name,?value.toString());
????????????}
????????}

????????return?map;
????}
}

七、ThreadLocal

ThreadLocal是線程內(nèi)的全局上下文。就是在單個(gè)線程中,方法之間共享的內(nèi)存,每個(gè)方法都可以從該上下文中獲取值和修改值。

實(shí)際案例:

在調(diào)用api時(shí)都會(huì)傳一個(gè)token參數(shù),通常會(huì)寫一個(gè)攔截器來校驗(yàn)token是否合法,我們可以通過token找到對(duì)應(yīng)的用戶信息(User),如果token合法,然后將用戶信息存儲(chǔ)到ThreadLocal中,這樣無論是在controller、service、dao的哪一層都能訪問到該用戶的信息。作用類似于Web中的request作用域。

傳統(tǒng)方式我們要在方法中訪問某個(gè)變量,可以通過傳參的形式往方法中傳參,如果多個(gè)方法都要使用那么每個(gè)方法都要傳參;如果使用ThreadLocal所有方法就不需要傳該參數(shù)了,每個(gè)方法都可以通過ThreadLocal來訪問該值。

  • ThreadLocalUtil.set("key", value); 保存值
  • T value = ThreadLocalUtil.get("key"); 獲取值
public?class?ThreadLocalUtil<T>?{
????private?static?final?ThreadLocal>?threadLocal?=?new?ThreadLocal()?{
????????@Override
????????protected?Map?initialValue()?{
????????????return?new?HashMap<>(4);
????????}
????};


????public?static?Map?getThreadLocal(){
????????return?threadLocal.get();
????}

????public?static??T?get(String?key)?{
????????Map?map?=?(Map)threadLocal.get();
????????return?(T)map.get(key);
????}

????public?static??T?get(String?key,T?defaultValue)?{
????????Map?map?=?(Map)threadLocal.get();
????????return?(T)map.get(key)?==?null???defaultValue?:?(T)map.get(key);
????}

????public?static?void?set(String?key,?Object?value)?{
????????Map?map?=?(Map)threadLocal.get();
????????map.put(key,?value);
????}

????public?static?void?set(Map?keyValueMap)?{
????????Map?map?=?(Map)threadLocal.get();
????????map.putAll(keyValueMap);
????}

????public?static?void?remove()?{
????????threadLocal.remove();
????}

????public?static??Map?fetchVarsByPrefix(String?prefix)?{
????????Map?vars?=?new?HashMap<>();
????????if(?prefix?==?null?){
????????????return?vars;
????????}
????????Map?map?=?(Map)threadLocal.get();
????????Set?set?=?map.entrySet();

????????for(?Map.Entry?entry?:?set){
????????????Object?key?=?entry.getKey();
????????????if(?key?instanceof?String?){
????????????????if(?((String)?key).startsWith(prefix)?){
????????????????????vars.put((String)key,(T)entry.getValue());
????????????????}
????????????}
????????}
????????return?vars;
????}

????public?static??T?remove(String?key)?{
????????Map?map?=?(Map)threadLocal.get();
????????return?(T)map.remove(key);
????}

????public?static?void?clear(String?prefix)?{
????????if(?prefix?==?null?){
????????????return;
????????}
????????Map?map?=?(Map)threadLocal.get();
????????Set?set?=?map.entrySet();
????????List?removeKeys?=?new?ArrayList<>();

????????for(?Map.Entry?entry?:?set?){
????????????Object?key?=?entry.getKey();
????????????if(?key?instanceof?String?){
????????????????if(?((String)?key).startsWith(prefix)?){
????????????????????removeKeys.add((String)key);
????????????????}
????????????}
????????}
????????for(?String?key?:?removeKeys?){
????????????map.remove(key);
????????}
????}
}

總結(jié):

這個(gè)是目前第三方數(shù)據(jù)接口交互過程中常用的一些參數(shù)與使用示例,希望對(duì)大家有點(diǎn)幫助。

當(dāng)然如果為了保證更加的安全,可以加上RSA,RSA2,AES等等加密方式,保證了數(shù)據(jù)的更加的安全,但是唯一的缺點(diǎn)是加密與解密比較耗費(fèi)CPU的資源。

推薦閱讀:


垃圾代碼和優(yōu)質(zhì)代碼的區(qū)別?

入職騰訊第九年,我辭職了

MyBatis 三種批量插入方式的對(duì)比 !

參考阿里規(guī)范,優(yōu)秀的 Java 項(xiàng)目代碼該如何分層?

30 行代碼實(shí)現(xiàn)螞蟻森林自動(dòng)收能量(附送源碼)

當(dāng)Docker遇到Intellij IDEA,再次解放了生產(chǎn)力~

我把 Spring Boot 的 banner 換成了美女,老板說工作不飽和,建議安排加班

一名外包程序員入職螞蟻金服,被質(zhì)疑到懷疑人生…

想接私活時(shí)薪再翻一倍,建議根據(jù)這幾個(gè)開源的SpringBoot項(xiàng)目(含小程序)改改~

瀏覽 35
點(diǎn)贊
評(píng)論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)
評(píng)論
圖片
表情
推薦
點(diǎn)贊
評(píng)論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 粉嫩小泬粉嫩小泬在线| 国产精品女| 少妇厨房愉情理伦BD在线观看| 一级内射片在线网站观看| 乱子伦一区二区三区视频在线观看| 3级毛片| 免费一级做a爱片毛片A片小说| 久久久久久综合| 亚洲AV无码久久寂寞少妇多毛| 欧美日韩在线视频免费播放| 日本高清视频www| 国产精品久久| 国产免费A片| 久久午夜视频| 成人做爰69片免费观看| 91精品人妻少妇无码影院| 久久不射网站| 亚洲瑟瑟| 亚欧黄色| 操B视频在线免费观看| 综合色国产精品欧美在线观看| 国产伦子伦一级A片免费看小说 | 久久V| 一区二区三区在线观看视频| 在线免费观看黄色电影| 中国操逼| 91农村站街老熟女露脸| 国产TS在线| 人人操人人摸人人爽| 亚洲成人一二三区| 激情婷婷六月| 伊人久久大香蕉视频| 精品免费囯产| 久久夜色视频网| 成人免费观看的毛视频| 国产精品无码在线观看| 97人人妻| 成人AV免费在线观看| 日韩人妻在线视频| 日韩小视频在线| 国产精品国产三级国产AⅤ原创 | 国产日韩精品无码去免费专区国产| 日韩高清毛片| 午夜福利在线视频| 色欲无码| 精品黑人| 久久久成人片| 在线观看av网站| 国产免费无码视频| 久久成人网豆花视频| 亚洲手机在线播放| 久久国产热| 制服丝袜一区| 内射一区二区| 小小拗女BBw搡BBBB搡| 亚洲av无码精品| 久久精品视频久久| 免费一级黄色毛片| 日韩在线观看AV| 国产操逼免费| 国产精品色情A级片| 中文视频免费播放| 欧美丝袜脚交xxxxBH| 日韩一级免费| 日韩一级黄色片| 国产精品久久777777| 18禁在线播放| 国产成人在线播放| 日韩精品视频在线| 中文字幕在线视频观看| 日韩视频中文字幕| 九九热精品| 大香蕉黄色电影| 人人操超碰| 久久一级片| 五十路在线| 操逼免费看| 欧美性爱网址| 操骚屄视频| 国产乱子伦视频国产印度| 欧美三级片在线视频| 中文字幕免费高清网站| 无码人妻精品一区二区三区99仓| 91亚洲精品乱码久久久久久蜜桃| 欧美特黄AAAAAAAAA片| 18毛片| 一道本av| 91成人小电影| 人人人人人操| 成人不卡| 国产欧美在线观看| 亚洲三级视频| 一级黄色电影A片| 在线中文字幕777| 亚洲无码操逼视频| 在线观看中文字幕视频| 麻酥酥在线视频| 91乱了伦国产乱子伦| 亚洲av黄片| 激情久久综合| 一级片黄片| 亚洲成人无码精品| 亚洲欧美影院| AV无码中文| 日韩VA| 日韩性爱视频在线观看| 俺也干| A片视频在线观看| 91偷拍视频| 国产精品一二三区| 中文字幕在线观看第一页| 人人摸人人看| 北条麻妃无码一区三区| 91精品国产人妻| 色婷婷欧美| 国产操逼无码| 亚洲一区翔田千里无码| 黄色三级电影| 日本一区免费| 欧美一級黃色A片免費看| 色色五月天婷婷| 日本免费黄色电影| 蜜桃一区二区视频在线观看| 亚洲秘AV无码一区二区qq群| 天天谢天天干| 亚洲中文字幕无码在线观看| 午夜丁香婷婷| 亚洲无码激情视频| 91在线无码精品秘入口男同| 欧美精品日韩在线观看| 视色网| 国产精品1| 成人无码精品| 操逼逼一区二区三区| 中国女人如毛片| 干少妇视频| 中文字幕一级A片高清免| 黄在线免费观看| 四虎影院在线| 中文字幕日韩高清| 免费无码一区二区三区| 中文字幕日韩人妻| 午夜亚洲AV永久无码精品蜜芽| 怕怕怕视频| 少妇搡BBBB搡BBB搡18禁| 男女拍拍拍拍| 日本中文在线观看| 国产精品久久毛片A片| 免费毛片网址| 激情婷婷五月| 日本操逼在线播放| 无码电影视频| 国产精品美女久久久久久久久| 日韩AV中文字幕在线播放| 午夜激情乱伦| 黄片一区二区三区| www在线| A亚洲天堂| 免费看黃色AAAAAA片| 插菊花综合网2| 手机AV在线| 日韩一级一片| 99资源站| 精品国产一| 伊人婷婷大香蕉| 久久精品黄色| 精品九九九| 亚洲精品在线观看视频| 日韩欧美国产精品| 91香蕉视频免费| 午夜尤物| 另类综合激情| 日韩在线观看免费| 欧美偷拍视频| 久久精品人人| 精品无码在线观看视频| BBWBBw嫩| 91大长腿美女花外围在线观看| 无码三级视频| 日韩精品一区二区三区四在线播放 | 日韩东京热中文字幕| 影音先锋成人AV| 国产精品久久精品| 在线观看视频免费无码免费视频| 91无码人妻东京热精品一区| 日本黄色精品| 午夜福利100| 一区二区三区四区无码| 亚洲AV成人无码网天堂| 99热欧美| 欧洲成人午夜精品无码区久久| a欧美| 2018天天干天天操| 色婷婷综合网| 久久久国产精品视频| 黄片免费视频| 丁香花免费高清视频小说完整| 日韩中文字幕视频在线观看| V在线| 一本道高清无码视频| 中文字幕在线观看1| 五月丁香亚洲综合| 婷婷午夜精品久久久久久性色| 91人妻人人澡人人爽人人精 | 97超碰人人| 天天干天天日蜜臀色欲av| 亚洲天堂成人在线| 中文字幕四区| 特黄网站| 欧美男人天堂网| 色色三区| 午夜高清视频| 成人免费黄片| 国产精品精品| 亚洲男人的天堂AV| 人人干人人干人人| 九九免费视频| 精品无码免费视频| AV无码免费一区二区三区不卡| 欧美性猛交XXXX乱大交3| 丰满人妻一区二区三区视频在线不卡 | 激情麻豆| 狼友视频首页| 免费看A| 色丁香视频在线观看的| 日韩精品中文字幕在线观看| 黄片小视频在线观看| 山东wBBBB搡wBBBB| 操干视频| AV大片在线观看| 日韩欧美分区视频| 日韩无码中文字幕| 在线成人自拍| 国产凹凸视频| 一区二区亚洲| 久久撸在线视频| 色老板在线免费观看| 国内自拍视频在线观看| 久久国产精| 免费无码蜜臀在线观看| 91美女视频| 中文字字幕中文字幕乱码| 欧洲综合视频| 免费内射视频| 天美果冻麻豆国产一区| 99精品国产热久久91色欲| 免费手机av| 在线播放亚洲| 特级西西444www| 人人操人人摸人人看| 亚洲图片欧美色图| 国产高潮视频在线观看| 想要xx在线观看| 操逼动漫| 国产精品欧美激情| 中国一级黄色毛片| 夜夜嗨老熟女AV一区二区三区| 亚洲三级无码在线观看| 看肏屄视频| 91中文字幕在线| 成人国产片| 综合久久中文字幕| 欧美日韩成人在线| 人人摸人人操人人爱| 亚洲欧美成人电影| 99re| 日逼免费| 亚洲国产激情| 色香蕉视频在线观看| 黄色av免费网站| 蜜桃传媒一区二区亚洲| 亚洲国产精品久久久久婷婷老年 | 日日操人人操| 中文字幕-区二区三区四区视频中国| 99re6热在线精品视频功能| 毛片日韩| 免费成人毛片| 午夜爽爽视频| 一区二区三区无码高清| 日韩毛片在线| 好男人一区二区三区在线观看| 色色色777| 久久嫩草精品久久久久精| 成人A∨| 久久草草热国产精品| 91精品国产人妻| 四虎成人无码| 国产91在线视频| 日韩中文字幕专区| 久久精品大香蕉| 大香蕉伊人成人网| 无码日韩人妻精品久久蜜桃| 国产第二页| 欧美高清一区二区| 大香伊人中文字幕精品| 丁香五月亭亭| 噜噜噜色| www.中文字幕| 国产成人AV一区二区三区在线观看| 91狠狠综合久久久久久| 国产AV美女| 青青草手机在线观看| 天天干夜夜操| 无码爆操| 国产精品久久久久久久久久王安宇 | 日韩高清一级免费| 天天插天天日| 成人片成人网久久蜜桃臀| 色黄视频在线观看| 人妻熟女字幕一区二区| 国产无码电影网| 无码视频一区二区三区| www.久久网| 男女做爱网站| 成人av黄色三级片在线观看| 亚洲无码婷婷| 午夜福利黄色| 五月天天| 亚洲97| 色老久久| 成人三级无码| 欧美特黄AAAAAA| 俺去俺来也www色官网cms| 69成人精品视频| 四虎成人免费视频| 蜜挑视频一区二区三区| H片免费在线观看| 日日撸| 成人精品一区日本无码网站suv | 久久国际精品| 日韩欧美视频一区国产欧美在线| 伊人精品在线| 国产乱伦视频| 少妇搡BBBB搡BBB搡AA| 欧美成人综合| 91黑人丨人妻丨国产丨| 成人黄色免费| 另类老妇奶性BBWBBwBBw| 免费黄色在线视频| 国产日韩中文字幕| 中文一级片| 久9精品| 玖玖资源在线| 99久久婷婷国产综合| 伊人婷婷| 国产精品久久久久久99| 亚洲无码不卡| 在线播放亚洲无码| 操逼逼网| 一色综合| 国产午夜视频| 少妇搡BBBB搡BBB搡AA| 浙江妇搡BBBB搡BBBB| 青草视频网| 操东北女人| 色老板最新地址| 欧美99| 九九午夜| 日韩性爱一区二区| 精品视频无码| 69堂在线观看| 北条麻妃无码精品AV| 天天夜夜狠狠| A黄色片| 免费爱爱网站| www.干| 国产小视频在线免费观看| 欧美A片在线观看| 国产网友自拍| 91成人在线视频| 三级网站网址| 在线不卡免费Av| 青娱乐老视频| AV无码资源| 国产天堂网| 亚洲日本中文字幕在线观看| 国产在线a| 国产成人精品免高潮在线观看| 日本www色| 91欧美性爱| 亚洲成人中文字幕| 黑人巨大精品欧美| 国产成人无码毛片| 毛片毛片毛片毛片毛片毛片| 久操久操久操| 撸一撸在线视频| 校园春色亚洲色图| 91AV电影| 污网站免费观看| 伊人丁香| 口爆吞精在线观看| 午夜福利123| av女人天堂| 2014av天堂网| AV电影免费看| 亚洲电影av| 91久久人澡人妻人人澡人人爽| 五月激情综合网| 国产乱伦一区| www一个人免费观看视频www| 日韩激情AV| 黄色香蕉网站| www.51av| 西西4444大胆无码视频| 丝袜美女足交| 伊人中文在线| 性爱av在线观看| 无码网| 国产成人大香蕉| 欧美激情内射| www国产精品| 九一成人网| 亚洲中文字幕第一页| 91福利视频在线观看| 搞搞电影91| av三级片在线观看| 国产精品久久久久久无人区| 91在线免费视频| 成人高清无码视频| 91丨国产丨白丝| 性BBwBBwBBwBBw禽| 中文在线观看免费视频| 国产精品视频一区二区三区在线观看 | 欧美成人A级片| www.91在线| 超碰综合| 空姐白洁| 亚洲性爱影院| 九一成人网| 91福利在线观看| 91精品丝袜久久久久久久久粉嫩| 熟妇操逼视频| 美女被操网站| 国产亚洲久一区二区三区| 91传媒在线免费观看| 特级西西人体WWWww| 亚久久久| 日韩中文字幕成人| 五十路在线视频| 高清无码免费不卡| 免费观看一级A片| 日韩人妻一区| 中文字幕一区二区三区在线观看 | 亚洲欧美日韩久久| 色播av| 一本一道vs波多野结衣| 在线免费观看AV片| 国产成人精品一区二区三区视频| 亚洲综合免费观看高清完整| 日韩成人小电影| 欧美性交网| 狠狠躁婷婷天天爽综合| 国产网站在线| 自拍视频国产| 激情无码av| 久久久国产精品视频| 日韩在线视频中文字幕| 91视频免费在线看| 97人人操| 婷婷五月天综合| 操屄在线视频| 成人AV免费| 国产一级a毛一级a毛视频在线网站| 欧美888| 日本少妇bbw| 亚洲久久视频| 蜜臀99久久精品久久久懂爱| 黄色视频大全免费看| 久久久国产视频| 日韩色道| 日韩A∨| 久久久人妻无码精品蜜桃| 无码人妻一区二区三区| 国产精品久久久久精| 91精品国产乱码久久| 国产中文| 黄色伊人网| 182在线视频| 美女裸体网站国产| 日韩一区二区三区四区| 777无码| 天天狠狠操| 欧美亚洲三级片| 在线大香蕉| 91麻豆福利视频| 国产又爽又黄网站免费观看| 久久黄色网络| 中文字幕人妻无码| 日韩高清无码三级片| 久久久久久久AV| 日韩视频一级| 国产在线小电影| 三级片导航| 午夜福利无码电影| 日本成人中文字幕在线观看 | 成人亚洲综合| 成人在线看片| 99精品视频免费观看| 最近中文字幕mv第三季歌词| 特一级黄色视频| 亚洲无码伊人| 99re99| 永久免费视频| 久久熟女嫩草成人片免费| 91大神精品| 高清无码免费| 黄色视频视频| 久久黄色大片| 久久国产精品精品国产色婷婷| 99久久婷婷国产综合精品青牛牛| 国产福利av| 亚洲欧洲成人在线| 亚洲色青| 无码高清视频在线观看| 国产操穴视频| 无码成人片| 亚洲AV秘无码苍井空| 可以免费看av的网站| 大BBBw大BBBW另类| 网站色色免费看| 人人操操| 躁BBB躁BBB躁BBBBB乃| 国产精品天天狠天天看| 噜噜噜AV| 亭亭色| 欧美亚韩一区二区三区| 中文字幕在线日亚洲9| 亚洲码成人| 2020无码| yy午夜福利| 精品人妻一区二区三区含羞草| 大香蕉伊人在线观看视频| 一级特黄录像免费播放下载软件| 日韩午夜在线观看| 国产精品AV网站| 欧美一区二区三区在线| ThePorn人妻白浆| JULIA超乳JULIA无码| 亚洲毛片网站| 日欧一级片| 午夜五月天| 青青草手机在线视频| 五月婷婷六月天| 探花无码| 91精品婷婷国产综合久久蝌蚪| 午夜日屄| 午夜啪啪网站| 丰满人妻一区二区三区| 日韩人妻精品无码制服| 中文无码播放| 国产人妻精品一二三区| 18禁网站免费观看| 欧美成人精品A片免费一区99| 日韩无码一区二区三区| 乱伦性爱视频| 丁香五月色情| 亚洲小说区图片区都市| 日韩精品一区在线| 波多野吉衣av| 日本www视频| 国产AV18岁| 丁香五月网| 欧美国产日韩在线| ppypp电影频道| 青青草原视频在线| www国产在线| a片免费网址| 伊人蕉| 肉片无遮挡一区二区三区免费观看视频| 亚洲成人在线免费观看| 黑人无码AV黑人天堂无码AV| 欧美中文字幕在线播放| 69人妻人人澡人人爽久久| 第四色视频| 男女做爱无码| 亚洲成人怡红院| 国产黄色电影| 91你懂的| 久久水蜜桃| 色综合一区| 大香蕉精品在线视频| 亚洲无码精品一区| 99黄网| 国产精品久免费的黄网站| 亚洲影院第一页在线观看| 日韩免费在线视频观看| 亚洲精品综合| 亚洲色诱| 日韩精品人妻中文字幕| 国产1区2区3区| 999国产精品| 三上悠亚无码破解69XXX| 91蜜桃传媒在线观看| 91欧美精品成人综合在线观看| 日韩AV网站在线观看| 国产51视频| 精品久久免费| 久久R5| 超碰自拍| 蜜桃视频网站| 91蜜桃在线| 国产精视频| 国产欧美成人| 永久免费一区二区| 亚洲中文久久| 曰曰摸日日碰| 国产丰满乱子伦无码| 大香蕉综合在线观看| 妞干网国产| 日韩中文字幕一区二区| 国产成人午夜福利视频| AV无码毛片| 青草大香蕉| MAD033_后宫秘密陶子.| 高清无码免费视频| 超碰中文字幕| 波多野结衣网址| 九九色视频| 91精品久久香蕉国产线看观看| 国模私拍视频| 精品国产一区二区三区久久久蜜月| jizz国产精品| 四虎成人网址| 特级婬片AAAAAAA级| 精品一区二区三区视频| 国产亚洲天堂| 九九精品在线视频| 五月婷视频| 亚洲AV成人无码一区二区三区 | 靠比免费| 久久电影五月天| 国产成人在线视频| 亚洲高清无码在线观看| 成人三级片在线观看| 成人亚洲| 亚洲欧洲在线视频| 久久国产免费| 91无码精品| 神马午夜精品96| 日逼国产| 中文无码在线播放| 亚洲少妇视频| 自拍偷拍网站| 国产第二页| 亚洲第一伊人| 91人妻人人澡人人精品| 日本精品人妻无码77777| 中文字幕一二三区| 久久婷婷五月综合伊人| 日韩在线免费播放| 亚洲a电影| 欧美色一级| 男女精品一区| 日韩黄色电影在线免费观看| 国产又爽又黄视频| 水果派解说A∨无码区| 中文字幕免| 日韩做爱| 亚洲无码人妻一区| 91AV免费看| 亚洲成人在线一区| 免费的AV网站| 狠狠做深爱婷婷久久综合一区| 国产伦理一区| 亚洲日本无码50p| 在线播放一区二区三区| 青青久视频| 操美女久久| 亚洲免费看黄| 9久9久9久9久女女女女| 日本精品黄色视频| 亚洲欧美第一页| 黄色视频在线观看免费网站| 久久久久无码精品国产91福利| 亚洲人妻一区二区| 大香蕉在线伊| 北条麻妃人妻中文无码| 亚洲精品日韩无码| 国产又爽又黄免费网站校园里| 一区二区三区亚洲| 一区二区三区成人| 人人看人人摸| 蜜桃av秘一区二区三区| 日韩免费Av| 激情黄色毛片| 国产夫妻自拍av| a天堂在线| 免费高清无码| 大香蕉天天操| 中文字幕成人A片| 黄色一级免费看| 丁香婷婷视频| 艹逼视频网站| 成人性爱AV| 超碰大香蕉| 韩日美女性爱| 青草五月天| 影音先锋乱伦电影| 天天日天天综合| 欧美国产精品一区二区三区| 一本加勒比HEZYO东京热无码| 少妇厨房愉情理伦BD在线观看 | 噼里啪啦免费观看视频大全| 精品视频在线看| 91在线视频免费| 中文字幕精品在线视频| 在线免费看黄色视频| 大伊人久久| 午夜精品18| 亚洲AV免费在线观看| 日韩无码中文字幕| 五月天亚洲激情| 久操B| 日本在线一级| 成人性爱视频网站| 大香蕉中文网| 国产性爱网址| 久久伊| 99视频在线免费观看| 国产一级a毛一级a毛片视频黑人| 懂色一区二区二区在线播放视频| 日韩免费看片| 日本啪啪网站| 久久久久一区| 色婷婷在线无码精品秘人口传媒| ThePorn人妻白浆| 婷婷久久五月| 日本高清一区二区高清免费视频| 国产毛片欧美毛片高潮| 日本免费在线观看视频| 日韩一区二区三区免费视频| 一本大道东京热AV| 久久毛片视频| 一级A爱爱| 大香蕉777| 婷婷综合缴情亚洲另类在线 | 日韩有码中文字幕在线观看| 黄片无码免费观看| 免费毛片网| 亚洲www啪成人一区二区麻豆| 韩日美女性爱| 99AV| 精品视频免费在线观看| 国产v欧美| 国产精品久久久精品cos| 躁BBB躁BBB添BBBBBB| 欧美三级片在线播放| 国产狂喷水潮免费网站www| 成人福利免费视频| 欧美自拍第一页| 2021国产视频| 国产乱妇乱子伦视频免费观看让女人 | 菊花综合网| 亚洲美女视频网| a网站在线| a级网站| 成人爽a毛片一区二区免费 | 亚洲久久视频| www伦理片-韩国三级三级三级a三级-成人AV | 免费黄色一级视频| 国产精品污www在线观看| 国产一区二区三区视频在线观看| 亚洲AV成人无码精在线| 91激情在线| 亚洲无码十八禁| 日韩无码AV一区二区三区| 老婆中文字幕乱码中文乱码| 中文字幕在线观看日韩| 亚洲成人AV| 亚洲中文字幕日本| 国产成人在线视频免费| 久久只有精品| 色色9999| 国内夫妻【20p】| 性欧美一区二区| 五月天福利影院| 夜操| 成人在线中文字幕| 黄色视频在线观看亚洲一区二区三区免费| 97爱爱视频| 蜜桃亚洲AV无码一区二区三区| 风流少妇一区二区三区91| 五月婷婷激情网| 淫乱人妻| www九九| 日韩在线看片| 成人网站av| 亚洲色影院| 小黄片在线免费观看| 欧美亚洲成人在线观看| 亚洲三级黄色视频| 九九热精品在线视频| 巨乳无码噜噜噜久久久| 欧一美一婬一伦一区二区三区 | 日韩在线综合| mm131亚洲国产精品久久| 日韩精品一区二区三区在线观看免费 | 影音先锋91| 狠狠躁日日躁夜夜躁A片小说免费| 操逼视频在线看| 亚洲高清免费| 色情片在线播放| 国内精品内射| 欧美亚洲日韩中文字幕| 黄色电影免费在线观看| 国产ts视频| 91西安站街老熟女露脸| 中文字幕日韩av| 成人伊人网| 亚洲午夜影院在线| 精品无码一区二区Av蜜桃| 一级日逼片| 麻豆传媒在线观看| 天天澡日日久| 91香蕉视频免费在线观看| 青娱乐无码| 99久久99久国产黄毛片| 少妇喷水在线观看| 欧美A片在线播放| 超碰成人免费| 黄色插逼视频| 国产免费一级特黄A片| 中文字幕777| 亚洲色图欧美| 爱搞搞就要爱搞搞| 天天干天天日天天射| 日本精品一区二区三区四区的功能 | 国产精品视频网站| 亚洲婷婷在线| av日韩在线播放| 午夜福利视频网站| 不卡av在线| 国产人国产视频成人免费观看…| 动漫无码视频| 成人免费毛片蓝莓| 久热精品视频| 亚洲91无码精品一区在线播放| 97AV人妻无码视频二区| 人人干人人艹| 天天干夜夜操熟女| 中文字幕巨肉乱码中文乱码| 狼友无码| 正在播放李彩斐被洋老外| 国产91无码精品秘入口| 午夜精品久久久| 97毛片| 伊人大香蕉在线网| 日韩视频――中文字幕| www.大鸡巴| 人妻无码在线观看| 毛片网站免费| 国产又爽又黄免费网站校园里| 麻豆黄片| 久久精品在线播放| 日日摸日日| 丰满人妻一区二区三区Av猛交 | 东京热在线免费观看| 偷偷撸在线| 日韩在线成人中文字幕亚洲| 国产在线观看无码免费视频| 土耳其电影《爱与罚》| 就爱搞搞| 波多野成人无码精品视频| 亚洲精品乱码久久久久久按摩观 | 福利色播| 国产一级视频| 一区二区三区Av| 国产乱子伦视频国产印度| 丁香婷婷男人天堂| 91高清无码视频| 免费看的黄色视频| 午色婷婷国产无码| 黄色录像毛片| 日韩一级免费毛片| 涩久久久| 99er在线| 国产内射在线观看| 夜夜bb| 亚州av| 欧美三级在线| 天天天日天天天天天天天日歌词| 精品一区二区三区四区视频| 91麻豆免费看| 日日搔av一区二区三区| www.91久久| 444444在线观看免费高清电视剧木瓜一 | 日韩美女在线| 婷婷久久五月天| av亚洲波多野结衣白嫩水多波| 国产精品久久久久久久久夜色| 亚洲性精| 婷婷五月天影视| 亚洲日韩国产AV无码无码精品| 人人妻人人玩澡人人爽| 国产传媒_色哟哟| 高清无码免费在线观看| 久久久高清无码视频| 人人干人人干人人| 国产欧美在线观看不卡| 超碰免费91|