最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot3 + Sa-Token 雙Token登錄認(rèn)證實戰(zhàn)案例解析

 更新時間:2026年02月24日 10:10:32   作者:碼路星河  
本文詳細(xì)介紹了如何在SpringBoot3項目中使用Sa-Token框架實現(xiàn)雙Token登錄認(rèn)證,全面展示了雙Token登錄認(rèn)證的實現(xiàn)過程,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧

做后端開發(fā)的都懂,登錄認(rèn)證是項目的基礎(chǔ)防線,而Token認(rèn)證又是前后端分離架構(gòu)下的首選方案。但單Token方案的痛點太明顯——要么Token有效期設(shè)短,用戶頻繁重新登錄,體驗拉胯;要么設(shè)長,Token泄露后風(fēng)險極高。

之前做SpringBoot3項目時,試過自己手寫JWT雙Token邏輯,處理過期刷新、Token校驗、異常攔截一套下來,冗余代碼一大堆,還踩了不少分布式部署下的緩存一致性坑。后來換成Sa-Token框架,發(fā)現(xiàn)它原生支持雙Token(AccessToken + RefreshToken)模式,幾行配置+簡單編碼就能落地,省了不少事。

這篇博客不搞虛的,不堆砌概念,全程以實戰(zhàn)為主,結(jié)合我實際開發(fā)中踩過的坑,手把手教大家用SpringBoot3整合Sa-Token實現(xiàn)雙Token登錄認(rèn)證,新手也能直接照搬用,老鳥也能避坑提速。

先說明下環(huán)境:SpringBoot 3.2.2 + Sa-Token 1.44.0(最新穩(wěn)定版,適配SpringBoot3) + Redis 7.2(分布式部署必備,單機(jī)可省略但建議部署) + JDK 17(SpringBoot3最低要求)。

一、為什么要用雙Token?(實際開發(fā)痛點出發(fā))

很多新手會問,單Token不夠用嗎?舉兩個實際開發(fā)中的場景,你就懂了:

  • 場景1:用戶登錄后,Token有效期設(shè)1小時,1小時后用戶正在操作,突然提示重新登錄,體驗極差;如果設(shè)7天,Token被泄露,別人能長時間盜用用戶賬號,安全風(fēng)險高。
  • 場景2:分布式項目中,單Token存在緩存同步問題,一旦某個節(jié)點Token失效,其他節(jié)點無法及時感知,導(dǎo)致用戶明明已登出,卻還能短暫訪問接口。

雙Token方案正好解決這兩個痛點,核心邏輯很簡單(不用死記概念,理解就行):

  • AccessToken(訪問令牌):短期有效(比如30分鐘),專門用來訪問業(yè)務(wù)接口,過期后無法訪問接口,但不用用戶重新登錄。
  • RefreshToken(刷新令牌):長期有效(比如7天),專門用來刷新AccessToken,不參與業(yè)務(wù)接口訪問,即使泄露,沒有AccessToken也無法操作業(yè)務(wù),且可快速注銷。

補(bǔ)充一句:Sa-Token的雙Token不是簡單生成兩個JWT,而是內(nèi)置了Token生命周期管理、刷新機(jī)制、緩存同步,比自己手寫JWT雙Token靠譜多了,還能避免重復(fù)造輪子。

二、前期準(zhǔn)備(依賴+配置,避坑重點)

這一步是基礎(chǔ),也是最容易踩坑的地方,尤其是SpringBoot3和Sa-Token的版本適配,還有Redis的配置,新手一定要仔細(xì)看。

2.1 引入依賴(pom.xml)

SpringBoot3整合Sa-Token,必須引入專門適配SpringBoot3的starter,不能用SpringBoot2的starter(否則會報“未能獲取有效的上下文處理器”錯誤),具體依賴如下,直接復(fù)制即可:

<!-- SpringBoot3 Web依賴(基礎(chǔ)必備) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Sa-Token SpringBoot3 starter(核心依賴,適配SpringBoot3) -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot3-starter</artifactId>
    <version>1.44.0</version>
</dependency>
<!-- Sa-Token 整合Redis(分布式部署必備,單機(jī)可省略,但建議加上) -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot3-starter</artifactId>
    <version>1.44.0</version>
</dependency>
<!-- Redis依賴(SpringBoot3默認(rèn)適配) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 工具類依賴(簡化代碼,可選但推薦) -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.28</version>
</dependency>

避坑提示1:Sa-Token的starter和dao-redis版本必須一致,否則會出現(xiàn)依賴沖突;1.44.0是目前最新穩(wěn)定版,支持雙Token反查、密鑰輪換等實用特性,建議直接用這個版本。

避坑提示2:如果是微服務(wù)項目,Sa-Token的starter不要放到父工程pom.xml中,要單獨放到每個子服務(wù)中,否則會出現(xiàn)啟動時獲取不到Web上下文的錯誤。

2.2 配置文件(application.yml)

配置文件主要分三部分:Sa-Token核心配置、Redis配置、Web配置,注釋寫得很詳細(xì),直接復(fù)制修改Redis地址即可:

server:
  port: 8080 # 項目端口,可自定義
# Spring Redis配置(分布式部署必備,單機(jī)可省略但建議配置)
spring:
  redis:
    host: 127.0.0.1 # Redis地址,本地默認(rèn)127.0.0.1
    port: 6379 # Redis端口,默認(rèn)6379
    password: 123456 # 你的Redis密碼,沒有則留空
    database: 0 # Redis數(shù)據(jù)庫索引,默認(rèn)0
    timeout: 10000ms # 連接超時時間
# Sa-Token核心配置(重點,雙Token相關(guān)配置)
sa-token:
  # 1. 基礎(chǔ)配置
  token-name: satoken # Token在請求頭中的名稱(默認(rèn)satoken,可自定義,比如Authorization)
  token-style: uuid # Token生成風(fēng)格(uuid更安全,可選:uuid、simple-uuid、random-32等)
  is-concurrent: true # 是否允許同一賬號多地同時登錄(true允許,false新登錄擠掉舊登錄)
  # 2. 雙Token配置(核心中的核心)
  access-token-timeout: 1800 # AccessToken有效期,單位:秒(30分鐘,可自定義)
  refresh-token-timeout: 604800 # RefreshToken有效期,單位:秒(7天,可自定義)
  refresh-token-single: true # 是否同一賬號只生成一個RefreshToken(true更安全,避免多刷新令牌泄露)
  # 3. Redis配置(整合Redis,分布式部署必備)
  redis-model: standalone # Redis模式(單機(jī):standalone,集群:cluster,哨兵:sentinel)
  redis-host: ${spring.redis.host} # 復(fù)用Spring Redis配置,不用重復(fù)寫
  redis-port: ${spring.redis.port}
  redis-password: ${spring.redis.password}
  redis-database: ${spring.redis.database}
  # 4. 異常配置(可選,自定義異常提示,更友好)
  not-login-message: 請先登錄!
  token-expire-message: 訪問令牌已過期,請刷新令牌!
  refresh-token-expire-message: 刷新令牌已過期,請重新登錄!

避坑提示3:access-token-timeout和refresh-token-timeout的單位是秒,不是毫秒,新手容易寫錯,導(dǎo)致Token有效期不符合預(yù)期(比如設(shè)1800000,以為是30分鐘,實際是500小時)。

避坑提示4:如果不配置Redis,Sa-Token默認(rèn)用內(nèi)存存儲Token,單機(jī)環(huán)境沒問題,但分布式環(huán)境會出現(xiàn)Token不共享的問題,建議不管是單機(jī)還是分布式,都配置Redis,避免后續(xù)擴(kuò)展麻煩。

三、核心代碼實現(xiàn)(實戰(zhàn)為主,復(fù)制即用)

核心邏輯分4步:用戶登錄生成雙Token、接口訪問攔截校驗Token、刷新AccessToken、用戶登出銷毀雙Token。代碼都經(jīng)過實際測試,沒有冗余,新手可以直接復(fù)制到項目中,替換自己的業(yè)務(wù)邏輯即可。

3.1 實體類(User.java)

簡單的用戶實體類,對應(yīng)數(shù)據(jù)庫用戶表,這里只寫核心字段,實際項目中可根據(jù)需求擴(kuò)展:

package com.example.doubleToken.entity;
import lombok.Data;
/**
 * 用戶實體類(對應(yīng)數(shù)據(jù)庫用戶表)
 * 實際項目中可根據(jù)需求擴(kuò)展字段,比如手機(jī)號、郵箱、角色等
 */
@Data
public class User {
    /**
     * 用戶ID(主鍵)
     */
    private Long id;
    /**
     * 用戶名(登錄賬號)
     */
    private String username;
    /**
     * 密碼(數(shù)據(jù)庫中建議加密存儲,比如用BCrypt加密)
     */
    private String password;
    /**
     * 用戶名(展示用,可選)
     */
    private String nickname;
}

3.2 登錄接口(生成雙Token)

用戶登錄時,校驗用戶名密碼正確后,用Sa-Token的StpUtil.loginWithRefreshToken()方法生成雙Token,該方法會自動處理Token的生命周期和緩存,比自己手寫簡單太多。

package com.example.doubleToken.controller;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.example.doubleToken.entity.User;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
 * 登錄相關(guān)接口(核心:生成雙Token)
 */
@RestController
@RequestMapping("/auth")
public class AuthController {
    /**
     * 用戶登錄(生成雙Token)
     * @param user 登錄參數(shù)(username + password)
     * @return 雙Token + 用戶信息
     */
    @PostMapping("/login")
    public SaResult login(@RequestBody User user) {
        // 1. 校驗用戶名密碼(實際項目中,這里要從數(shù)據(jù)庫查詢用戶,比對密碼,建議加密比對)
        // 這里模擬校驗,實際項目中替換為自己的業(yè)務(wù)邏輯
        if (!"admin".equals(user.getUsername()) || !"123456".equals(user.getPassword())) {
            return SaResult.error("用戶名或密碼錯誤");
        }
        // 2. 生成雙Token(核心代碼,Sa-Token原生支持)
        // 參數(shù)1:用戶ID(唯一標(biāo)識,建議用數(shù)據(jù)庫主鍵)
        // 參數(shù)2:登錄設(shè)備類型(可選,比如pc、app、wechat,用于同端互斥登錄)
        StpUtil.login(user.getId(), "pc");
        // 3. 獲取生成的雙Token(返回給前端,前端保存)
        String accessToken = StpUtil.getTokenValue(); // AccessToken
        String refreshToken = SaTempUtil.createToken(user.getId(), 2592000);
        // 4. 組裝返回結(jié)果(返回Token + 用戶信息,前端按需保存)
        Map<String, Object> data = new HashMap<>();
        data.put("accessToken", accessToken);
        data.put("refreshToken", refreshToken);
        data.put("tokenType", "Bearer"); // 規(guī)范寫法,前端請求時拼接在Token前
        data.put("expiresIn", StpUtil.getTokenTimeout()); // AccessToken剩余有效期(秒)
        data.put("user", user); // 用戶信息,實際項目中可返回脫敏后的信息
        return SaResult.ok("登錄成功").setData(data);
    }
}

重點說明:Sa-token會自動完成3件事:生成AccessToken和RefreshToken、將Token信息存入Redis、綁定用戶ID和Token的關(guān)聯(lián)關(guān)系,不用我們手動處理任何緩存邏輯。

避坑提示5:登錄時的密碼校驗,實際項目中一定要加密比對(比如用BCrypt加密),不要明文存儲密碼,也不要明文比對,否則會有嚴(yán)重的安全風(fēng)險。

3.3 Token校驗攔截器(全局?jǐn)r截,無需手動校驗)

Sa-Token提供了全局?jǐn)r截器,我們只需簡單配置,就能實現(xiàn)“未登錄攔截”“Token過期攔截”,不用在每個接口中手動寫校驗代碼,極大簡化開發(fā)。

package com.example.doubleToken.config;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
 * Sa-Token全局?jǐn)r截器配置(校驗Token,未登錄/Token過期攔截)
 */
@Configuration
public class SaTokenConfig implements WebMvcConfigurer {
    /**
     * 注冊Sa-Token攔截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注冊全局?jǐn)r截器,攔截所有接口
        registry.addInterceptor(new SaInterceptor(handle -> {
            // 校驗AccessToken是否有效(核心校驗邏輯,一行代碼搞定)
            StpUtil.checkLogin();
            // 可選:校驗Token的設(shè)備類型(防止不同設(shè)備混用Token,提升安全性)
            // StpUtil.checkLoginType("pc");
        }))
        // 攔截所有接口
        .addPathPatterns("/**")
        // 排除不需要攔截的接口(登錄、刷新Token、登出接口,必須排除)
        .excludePathPatterns(
                "/auth/login",
                "/auth/refreshToken",
                "/auth/logout"
        );
    }
}

說明:StpUtil.checkLogin()方法會自動校驗請求頭中的AccessToken是否有效、是否過期,如果無效或過期,會自動拋出對應(yīng)的異常(NotLoginException、TokenExpireException),并返回我們在配置文件中自定義的異常提示。

避坑提示6:一定要排除登錄、刷新Token、登出接口,否則會出現(xiàn)“自己攔截自己”的問題,導(dǎo)致用戶無法登錄、無法刷新Token。

3.4 刷新AccessToken接口

當(dāng)AccessToken過期后,前端攜帶RefreshToken請求該接口,生成新的AccessToken(RefreshToken不變,除非RefreshToken也過期),實現(xiàn)用戶無感知續(xù)期,不用重新登錄。

package com.example.doubleToken.controller;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
 * 刷新Token接口(核心:AccessToken過期后,用RefreshToken續(xù)期)
 */
@RestController
@RequestMapping("/auth")
public class RefreshTokenController {
    /**
     * 刷新AccessToken
     * @param refreshToken 前端傳入的RefreshToken
     * @return 新的AccessToken
     */
    @PostMapping("/refreshToken")
    public SaResult refreshToken(@RequestParam String refreshToken) {
        try {
            // 1、驗證
            Object userId = SaTempUtil.parseToken(refreshToken);
            if(userId == null) {
                return SaResult.error("無效 refreshToken");
            }
            // 2、為其生成新的短 token
            String accessToken = StpUtil.createLoginSession(userId);
            // 3、返回
            return SaResult.data(accessToken);
        } catch (Exception e) {
            // 異常說明:RefreshToken過期、無效,都會進(jìn)入這里,提示用戶重新登錄
            return SaResult.error("刷新Token失敗,請重新登錄").setCode(401);
        }
    }
}

重點說明:Sa-Token會自動處理3件事:校驗RefreshToken的有效性、生成新的AccessToken、更新Redis中Token的有效期,RefreshToken本身的有效期不會變,直到它自己過期。

3.5 登出接口(銷毀雙Token)

用戶登出時,需要同時銷毀AccessToken和RefreshToken,避免Token被復(fù)用,Sa-Token提供了StpUtil.logout()方法,一鍵銷毀雙Token,不用手動操作Redis。

package com.example.doubleToken.controller;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * 登出接口(核心:銷毀雙Token)
 */
@RestController
@RequestMapping("/auth")
public class LogoutController {
    /**
     * 用戶登出(銷毀雙Token)
     * @return 登出結(jié)果
     */
    @PostMapping("/logout")
    public SaResult logout() {
        // 核心代碼:一鍵銷毀當(dāng)前用戶的AccessToken和RefreshToken
        // 會自動刪除Redis中的Token信息,解除用戶與Token的關(guān)聯(lián)
        StpUtil.logout();
        return SaResult.ok("登出成功");
    }
}

避坑提示7:登出時一定要用StpUtil.logout()方法,不要自己手動刪除Redis中的Token,因為Sa-Token會在Redis中存儲多個與Token相關(guān)的鍵值對,手動刪除容易刪不干凈,導(dǎo)致Token殘留,出現(xiàn)安全風(fēng)險。

3.6 測試接口(驗證Token校驗)

寫一個簡單的測試接口,驗證Token校驗是否生效,登錄后才能訪問,未登錄或Token過期則被攔截:

package com.example.doubleToken.controller;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * 測試接口(驗證Token校驗是否生效)
 */
@RestController
@RequestMapping("/test")
public class TestController {
    /**
     * 測試接口(需要登錄才能訪問)
     * @return 測試結(jié)果
     */
    @GetMapping("/hello")
    public SaResult hello() {
        // 獲取當(dāng)前登錄用戶ID(登錄后才能獲取,未登錄會被攔截)
        Long userId = StpUtil.getLoginIdAsLong();
        return SaResult.ok("訪問成功").setData("當(dāng)前登錄用戶ID:" + userId);
    }
}

四、實際測試(Postman測試,驗證全流程)

代碼寫完后,用Postman測試全流程,確保每個步驟都能正常運行,測試步驟如下(新手可照做):

4.1 測試登錄接口(生成雙Token)

  • 請求地址:POST http://localhost:8080/auth/login
  • 請求體(JSON):{"username":"admin","password":"123456"}
  • 預(yù)期結(jié)果:返回登錄成功,包含accessToken、refreshToken、用戶信息。

4.2 測試測試接口(未登錄攔截)

  • 請求地址:GET http://localhost:8080/test/hello
  • 請求頭:不攜帶任何Token
  • 預(yù)期結(jié)果:返回“請先登錄!”,狀態(tài)碼401。

4.3 測試測試接口(登錄后訪問)

  • 請求地址:GET http://localhost:8080/test/hello
  • 請求頭:Authorization: Bearer 你的accessToken(或satoken: 你的accessToken,對應(yīng)配置文件中的token-name)
  • 預(yù)期結(jié)果:返回“訪問成功”,包含當(dāng)前登錄用戶ID。

4.4 測試刷新Token接口(AccessToken過期后)

  • 先修改配置文件中的access-token-timeout為10(10秒過期),重啟項目,重新登錄獲取雙Token。
  • 等待10秒,讓AccessToken過期,再用過期的AccessToken訪問測試接口,預(yù)期返回“訪問令牌已過期,請刷新令牌!”。
  • 請求地址:POST http://localhost:8080/auth/refreshToken
  • 請求參數(shù):refreshToken=你的refreshToken
  • 預(yù)期結(jié)果:返回“Token刷新成功”,包含新的accessToken。
  • 用新的accessToken訪問測試接口,預(yù)期能正常訪問。

4.5 測試登出接口

  • 請求地址:POST http://localhost:8080/auth/logout
  • 請求頭:攜帶有效的accessToken
  • 預(yù)期結(jié)果:返回“登出成功”。
  • 用登出后的accessToken訪問測試接口,預(yù)期返回“請先登錄!”。

五、實際開發(fā)中的避坑總結(jié)(重中之重)

這部分是我實際開發(fā)中踩過的坑,整理出來,幫大家少走彎路,每一個坑都對應(yīng)實際場景,新手一定要牢記:

  • 坑1:SpringBoot3引入了SpringBoot2的Sa-Token starter,導(dǎo)致啟動報錯“未能獲取有效的上下文處理器”。解決方案:必須引入sa-token-spring-boot3-starter,版本與dao-redis一致。
  • 坑2:微服務(wù)項目中,將Sa-Token starter放到父工程,導(dǎo)致子服務(wù)啟動報錯。解決方案:將Sa-Token starter單獨放到每個子服務(wù)的pom.xml中。
  • 坑3:Token有效期配置錯誤,把秒當(dāng)成毫秒,導(dǎo)致Token有效期不符合預(yù)期。解決方案:記住sa-token配置中,timeout的單位是秒。
  • 坑4:攔截器沒有排除登錄、刷新Token接口,導(dǎo)致用戶無法登錄。解決方案:在攔截器配置中,excludePathPatterns排除相關(guān)接口。
  • 坑5:登出時手動刪除Redis中的Token,導(dǎo)致Token殘留。解決方案:統(tǒng)一用StpUtil.logout()方法銷毀雙Token。
  • 坑6:在非Web上下文(比如@Async方法、定時任務(wù))中調(diào)用StpUtil.getLoginId(),導(dǎo)致報錯“非web上下文無法獲取HttpServletRequest”。解決方案:避免在非Web上下文調(diào)用需要獲取Token的API,或手動傳遞用戶ID。
  • 坑7:密碼明文存儲、明文比對,存在安全風(fēng)險。解決方案:用BCrypt等加密算法加密存儲密碼,比對時解密比對。

六、總結(jié)與擴(kuò)展

到這里,SpringBoot3 + Sa-Token雙Token登錄認(rèn)證的實戰(zhàn)就完成了,整個流程下來,代碼量很少,大部分邏輯都由Sa-Token框架封裝完成,不用我們手動處理Token生成、緩存、過期、刷新等繁瑣邏輯,極大提升了開發(fā)效率。

對比自己手寫JWT雙Token,Sa-Token的優(yōu)勢很明顯:原生支持雙Token模式、內(nèi)置Redis緩存、分布式部署友好、API簡潔、異常處理完善,還支持同端互斥登錄、Token反查、密鑰輪換等實用特性,適合各種規(guī)模的SpringBoot項目。

擴(kuò)展建議(實際項目中可按需擴(kuò)展):

  • 密碼加密:用BCrypt加密存儲密碼,替換示例中的明文校驗邏輯。
  • 異常統(tǒng)一處理:自定義全局異常處理器,統(tǒng)一返回異常格式,更友好。
  • Token前綴:配置token-name為Authorization,前端請求時拼接Bearer前綴,符合RESTful規(guī)范。
  • 同端互斥登錄:在登錄時指定設(shè)備類型,配置is-concurrent為false,實現(xiàn)同一賬號同端只能登錄一次。
  • Token反查:利用Sa-Token 1.44.0的新特性,實現(xiàn)根據(jù)用戶ID反查Token,用于強(qiáng)制用戶登出等場景。

最后說一句:技術(shù)選型沒有最好的,只有最適合的。Sa-Token輕量、簡潔、易用,對于大部分SpringBoot項目來說,完全能滿足登錄認(rèn)證的需求,尤其是雙Token模式,落地簡單,避坑后幾乎沒有線上問題。

到此這篇關(guān)于SpringBoot3 + Sa-Token 雙Token登錄認(rèn)證實戰(zhàn)(避坑版)的文章就介紹到這了,更多相關(guān)SpringBoot3 Sa-Token雙Token登錄認(rèn)證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

和平县| 揭阳市| 潮安县| 鄯善县| 当阳市| 云阳县| 蓝田县| 固镇县| 郎溪县| 潮安县| 长葛市| 盖州市| 延长县| 两当县| 杂多县| 神木县| 喀喇| 山阳县| 梧州市| 绍兴县| 淄博市| 周宁县| 文成县| 司法| 曲麻莱县| 栖霞市| 图木舒克市| 泰州市| 景宁| 宿州市| 陆川县| 东光县| 马关县| 安阳县| 平安县| 嘉祥县| 库尔勒市| 常德市| 张掖市| 沁阳市| 广宁县|