精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

小紅書二面:什么是JWT?它是如何工作的?

開發 前端
有狀態服務,即服務端需要記錄每次會話的客戶端信息,從而識別客戶端身份,根據用戶身份進行請求的處理,典型的設計如 Tomcat 中的 Session。

一 無狀態登錄

1.1 什么是有狀態

有狀態服務,即服務端需要記錄每次會話的客戶端信息,從而識別客戶端身份,根據用戶身份進行請求的處理,典型的設計如 Tomcat 中的 Session。例如登錄:用戶登錄后,我們把用戶的信息保存在服務端 session 中,并且給用戶一個 cookie 值,記錄對應的 session,然后下次請求,用戶攜帶 cookie 值來(這一步有瀏覽器自動完成),我們就能識別到對應 session,從而找到用戶的信息。這種方式目前來看最方便,但是也有一些缺陷,如下:

  • 服務端保存大量數據,增加服務端壓力
  • 服務端保存用戶狀態,不支持集群化部署

1.2 什么是無狀態

微服務集群中的每個服務,對外提供的都使用 RESTful 風格的接口。而 RESTful 風格的一個最重要的規范就是:服務的無狀態性,即:

  • 服務端不保存任何客戶端請求者信息
  • 客戶端的每次請求必須具備自描述信息,通過這些信息識別客戶端身份

那么這種無狀態性有哪些好處呢?

  • 客戶端請求不依賴服務端的信息,多次請求不需要必須訪問到同一臺服務器
  • 服務端的集群和狀態對客戶端透明
  • 服務端可以任意的遷移和伸縮(可以方便的進行集群化部署)
  • 減小服務端存儲壓力

1.3 如何實現無狀態

無狀態登錄的流程:

  • 首先客戶端發送賬戶名/密碼到服務端進行認證
  • 認證通過后,服務端將用戶信息加密并且編碼成一個 token(一般是 JWT),返回給客戶端
  • 以后客戶端每次發送請求,都需要攜帶認證的 token
  • 服務端對客戶端發送來的 token 進行解密,判斷是否有效,并且獲取用戶登錄信息

二 JWT

2.1 JWT 簡介

JWT,全稱是 Json Web Token, 是一種 JSON 風格的輕量級的授權和身份認證規范,可實現無狀態、分布式的 Web 應用授權:

圖片圖片

JWT 作為一種規范,并沒有和某一種語言綁定在一起,常用的 Java 實現是 GitHub 上的開源項目 jjwt,地址如下:https://github.com/jwtk/jjwt

2.2 JWT 數據格式

JWT 包含三部分數據:

  • Header:頭部,通常頭部有兩部分信息:

聲明類型,這里是JWT

加密算法,自定義

我們會對頭部進行 Base64Url 編碼(可解碼),得到第一部分數據。

  • Payload:載荷,就是有效數據,在官方文檔中(RFC7519),這里給了7個示例信息:

iss (issuer):表示簽發人

exp (expiration time):表示token過期時間

sub (subject):主題

aud (audience):受眾

nbf (Not Before):生效時間

iat (Issued At):簽發時間

jti (JWT ID):編號

這部分也會采用 Base64Url 編碼,得到第二部分數據。

  • Signature:簽名,是整個數據的認證信息。一般根據前兩步的數據,再加上服務的的密鑰secret(密鑰保存在服務端,不能泄露給客戶端),通過 Header 中配置的加密算法生成。用于驗證整個數據完整和可靠性。

生成的數據格式如下圖:

圖片圖片

注意,這里的數據通過 . 隔開成了三部分,分別對應前面提到的三部分,另外,這里數據是不換行的,圖片換行只是為了展示方便而已。

2.3 JWT 交互流程

流程圖:

圖片圖片

步驟翻譯:

  1. 應用程序或客戶端向授權服務器請求授權
  2. 獲取到授權后,授權服務器會向應用程序返回訪問令牌
  3. 應用程序使用訪問令牌來訪問受保護資源(如 API)

因為 JWT 簽發的 token 中已經包含了用戶的身份信息,并且每次請求都會攜帶,這樣服務的就無需保存用戶信息,甚至無需去數據庫查詢,這樣就完全符合了 RESTful 的無狀態規范。

2.4 JWT 存在的問題

說了這么多,JWT 也不是天衣無縫,由客戶端維護登錄狀態帶來的一些問題在這里依然存在,舉例如下:

  1. 續簽問題,這是被很多人詬病的問題之一,傳統的 cookie+session 的方案天然的支持續簽,但是 jwt 由于服務端不保存用戶狀態,因此很難完美解決續簽問題,如果引入 redis,雖然可以解決問題,但是 jwt 也變得不倫不類了。
  2. 注銷問題,由于服務端不再保存用戶信息,所以一般可以通過修改 secret 來實現注銷,服務端 secret 修改后,已經頒發的未過期的 token 就會認證失敗,進而實現注銷,不過畢竟沒有傳統的注銷方便。
  3. 密碼重置,密碼重置后,原本的 token 依然可以訪問系統,這時候也需要強制修改 secret。
  4. 基于第 2 點和第 3 點,一般建議不同用戶取不同 secret。

對于上面提到的這些問題,在目前具體的項目實踐中,更多的是通過引入 Redis 來解決這些問題。

三 實戰

說了這么久,接下來我們就來看看這個東西到底要怎么用?

3.1 環境搭建

首先我們來創建一個 Spring Boot 項目,創建時需要添加 Spring Security 依賴,創建完成后,添加 jjwt 依賴,完整的 pom.xml 文件如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
</dependency>

然后在項目中創建一個簡單的 User 對象實現 UserDetails 接口,如下:

public class User implements UserDetails {
    private String username;
    private String password;
    private List<GrantedAuthority> authorities;
    public String getUsername() {
        return username;
    }
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @Override
    public boolean isEnabled() {
        return true;
    }
    //省略getter/setter
}

這個就是我們的用戶對象,先放著備用,再創建一個 HelloController,內容如下:

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello() {
        return "hello jwt !";
    }
    @GetMapping("/admin")
    public String admin() {
        return "hello admin !";
    }
}

HelloController 很簡單,這里有兩個接口,設計是 /hello 接口可以被具有 user 角色的用戶訪問,而 /admin 接口則可以被具有 admin 角色的用戶訪問。

3.2 JWT 配置

先準備一個 JWT 操作的工具類:

public class JwtUtils {

    public static final Integer EXPIRE_TIME = 7 * 24 * 60 * 60;
    public static final Integer REDIS_TOKEN_EXPIRE_TIME = 30 * 60;
    public static final String TOKEN_ISSUER = "javaboy";

    /**
     * 生成 JWT 字符串
     *
     * @return
     */
    public static String createJWT() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String jws = Jwts.builder()
                //設置頭部信息(相當于 JWT 字符串第一部分的內容)
                .header().add("type", "JWT")
                .and()
                //相當于 JWT 字符串第二部分的內容
                //簽名密鑰
                .signWith(getPrivateKey())
                //設置過期時間
                .expiration(java.util.Date.from(java.time.Instant.now().plusSeconds(EXPIRE_TIME)))
                //設置用戶名
                .subject(authentication.getName())
                //設置用戶權限,相當于把用戶權限轉為字符串 admin,user,xxx
                .claim("authorities", authentication.getAuthorities().stream().map(a -> a.getAuthority()).collect(Collectors.joining(",")))
                //令牌簽發時間
                .issuedAt(new Date())
                .issuer(TOKEN_ISSUER)
                .compact();
        return jws;
    }

    public static PrivateKey getPrivateKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        ClassPathResource resource = new ClassPathResource("private_key.pem");
        byte[] privateKeyBytes = FileCopyUtils.copyToByteArray(resource.getInputStream());
        String key = new String(privateKeyBytes, StandardCharsets.UTF_8);
        String privateStr = key
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replaceAll(System.lineSeparator(), "")
                .replace("-----END PRIVATE KEY-----", "");
        byte[] privateKeyDecodedBytes = Base64.getDecoder().decode(privateStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyDecodedBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

    public static RSAPublicKey getPublicKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        ClassPathResource resource = new ClassPathResource("public_key.pem");
        byte[] publicKeyBytes = FileCopyUtils.copyToByteArray(resource.getInputStream());
        String key = new String(publicKeyBytes, StandardCharsets.UTF_8);
        String publicStr = key
                .replace("-----BEGIN PUBLIC KEY-----", "")
                .replaceAll(System.lineSeparator(), "")
                .replace("-----END PUBLIC KEY-----", "");
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        byte[] publicKeyBase64Bytes = Base64.getDecoder().decode(publicStr);
        X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBase64Bytes);
        PublicKey rsaPublicKey = keyFactory.generatePublic(publicKeySpec);
        return (RSAPublicKey) rsaPublicKey;
    }

    public static Authentication verifyToken(String token) {
        try {
            Claims claims = Jwts.parser()
                    .verifyWith(getPublicKey()).build()
                    .parseSignedClaims(token).getPayload();
            String username = claims.getSubject();
            // user,admin,xxx
            String authorities = claims.get("authorities", String.class);
            // 解析用戶權限
            List<SimpleGrantedAuthority> list = Arrays.stream(authorities.split(",")).map(s -> new SimpleGrantedAuthority(s)).collect(Collectors.toList());
            return UsernamePasswordAuthenticationToken.authenticated(username, null, list);
        } catch (Exception e) {
            //令牌校驗失敗
            return null;
        }

    }
}

接下來,在用戶登錄成功的時候,生成 JWT 字符串,并存入到 Redis 中,如下:

@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests(a -> a.anyRequest().authenticated())
            .csrf(c -> c.disable())
            .sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .formLogin(f -> f
                    .successHandler((req, resp, auth) -> {
                        //登錄成功,生成 JWT 字符串
                        try {
                            String token = JwtUtils.createJWT();
                            //將 JWT 字符串保存到 redis 中
                            redisTemplate.opsForValue().set(auth.getName() + ":" + token, auth.getName());
                            // 設置過期時間
                            redisTemplate.expire(auth.getName() + ":" + token, JwtUtils.REDIS_TOKEN_EXPIRE_TIME, TimeUnit.SECONDS);
                            resp.setContentType("application/json;charset=utf-8");
                            RespBean respBean = new RespBean(200, token, null);
                            resp.getWriter().write(new ObjectMapper().writeValueAsString(respBean));
                        } catch (NoSuchAlgorithmException e) {
                            throw new RuntimeException(e);
                        } catch (InvalidKeySpecException e) {
                            throw new RuntimeException(e);
                        }
                    })
                    .permitAll())
            .logout(l -> l.logoutSuccessHandler((req, resp, auth) -> {
                // 刪除 redis 中的 token
                String key = auth.getName() + ":" + req.getHeader("Authorization").replace("Bearer ", "");
                System.out.println("key = " + key);
                redisTemplate.delete(key);
                resp.getWriter().write("logout success");
            }).logoutUrl("/logout").permitAll());
    http.addFilterAfter(new JwtFilter(redisTemplate), SecurityContextHolderFilter.class);
    return http.build();
}

最后再來一個校驗的過濾器,在用法發送請求的時候,校驗 JWT 字符串,如下:

public class JwtFilter extends GenericFilterBean {
    StringRedisTemplate redisTemplate;

    public JwtFilter(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {
        RespBean result = null;
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        resp.setContentType("application/json;charset=utf-8");
        try {
            //如果是登錄請求,則直接放行
            if (req.getRequestURI().equals("/login")) {
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
            //獲取請求頭中的token
            String token = req.getHeader("Authorization");
            if (token == null) {
                result = new RespBean(500, "令牌為空,請求失敗", null);
                PrintWriter out = resp.getWriter();
                out.write(new ObjectMapper().writeValueAsString(result));
            } else {
                //驗證token
                token = token.replace("Bearer ", "");
                //驗證token是否有效
                //校驗通過,則返回認證后的 Auhtentication 對象,否則返回 null
                Authentication authentication = JwtUtils.verifyToken(token);
                String s = redisTemplate.opsForValue().get(authentication.getName() + ":" + token);
                if (s == null) {
                    // 令牌失效
                    result = new RespBean(501, "令牌失效,請重新登錄", null);
                    resp.getWriter().write(new ObjectMapper().writeValueAsString(result));
                } else {
                    //令牌有效,檢查令牌過期時間,如果臨近過期,則為令牌續期
                    Long expire = redisTemplate.getExpire(authentication.getName() + ":" + token);
                    if (expire != null && expire < 10 * 60) {
                        //說明令牌還有 10 分鐘過期,則重新設置新的過期時間
                        redisTemplate.expire(authentication.getName() + ":" + token, Duration.ofSeconds(JwtUtils.REDIS_TOKEN_EXPIRE_TIME));
                    }
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                    filterChain.doFilter(servletRequest, servletResponse);
                }
            }
        } catch (Exception e) {

        } finally {
            // 清除上下文
            SecurityContextHolder.clearContext();
        }

    }
}

關于這個過濾器,我說如下幾點:

  1. 首先從請求頭中提取出 Authorization 字段,這個字段對應的 value 就是用戶的 token。
  2. 將提取出來的 token 字符串調用 JwtUtils.verifyToken 方法進行驗證,將驗證結果放到當前的 SecurityContext 中,然后執行過濾鏈使請求繼續執行下去。

3.3 Spring Security 配置

最后,在 Spring Security 中配置這個過濾器。

http.addFilterAfter(new JwtFilter(redisTemplate), SecurityContextHolderFilter.class);

搞定!

3.4 測試

做完這些之后,我們的環境就算完全搭建起來了,接下來啟動項目然后在 POSTMAN 中進行測試,如下:

圖片圖片

登錄成功后返回的字符串就是經過 base64url 轉碼的 token,一共有三部分,通過一個 . 隔開,我們可以對第一個 . 之前的字符串進行解碼,即 Header,如下:

圖片圖片

再對兩個 . 之間的字符解碼,即 payload:

圖片圖片

可以看到,我們設置信息,由于 base64 并不是加密方案,只是一種編碼方案,因此,不建議將敏感的用戶信息放到 token 中。

接下來再去訪問 /hello 接口,注意認證方式選擇 Bearer Token,Token 值為剛剛獲取到的值,如下:

圖片圖片

可以看到,訪問成功。

四 總結

這就是 JWT 結合 Spring Security 的一個簡單用法。

責任編輯:武曉燕 來源: 江南一點雨
相關推薦

2020-09-11 08:41:50

域名系統DNS網絡

2024-08-19 00:25:00

2024-07-30 14:01:51

Java字節碼JVM?

2024-09-03 10:15:21

2024-10-22 15:25:20

2024-09-27 16:33:44

2023-07-03 14:36:07

物聯網IoT

2025-04-03 08:00:00

灰度發布Java開發

2024-11-20 16:00:19

MybatisJava數據庫

2022-11-22 11:30:53

2024-11-15 16:15:59

2025-03-28 10:47:05

開發注解Java

2025-03-07 08:40:00

WAL數據庫分布式系統

2021-08-27 09:00:00

CDC數據庫技術

2020-10-13 12:29:38

Linux包管理器

2024-04-08 14:29:45

AI工廠數據中心

2024-12-26 17:04:47

2024-06-03 14:03:35

2021-04-25 09:58:48

mmapJava面試

2021-03-17 15:54:32

IO零拷貝方式
點贊
收藏

51CTO技術棧公眾號

日韩av手机在线| 亚洲女人天堂色在线7777| 先锋影音男人资源| 国产91免费在线观看| 老司机午夜精品视频| 另类视频在线观看| 一本色道久久综合亚洲精品图片| 日韩一级特黄| 欧美色另类天堂2015| 久久久一二三四| 日本啊v在线| 国产成人在线影院| 国产精品久久久av久久久| 欧美老熟妇一区二区三区| 免费欧美视频| 欧美v日韩v国产v| 蜜臀av免费观看| gogo高清午夜人体在线| 中文字幕一区二区三区不卡| 精品产品国产在线不卡| 中国男女全黄大片| 国产黄在线播放| 国产一区三区三区| 91精品国产91久久久久久| 999精品网站| 国产欧美日韩综合一区在线观看| 国产精品扒开腿做爽爽爽a片唱戏| 厕沟全景美女厕沟精品| 久久综合五月| 亚洲女人初尝黑人巨大| 香蕉视频xxxx| 五月天激情婷婷| 日韩高清欧美激情| 成人av电影在线网| 国产精品免费福利| 亚洲综合一二三| 午夜久久tv| 日韩中文字幕不卡视频| avtt香蕉久久| av网址在线播放| 国产精品久久影院| 色狠狠久久av五月综合| 九一国产在线| 成人avav影音| 国产精品青青草| 亚洲国产精品视频在线| 国产精品一区免费视频| 成人欧美一区二区三区黑人| 在线视频欧美亚洲| 久久福利视频一区二区| 国产美女久久精品香蕉69| 亚洲婷婷久久综合| 美女在线一区二区| 国产日本欧美一区| 亚洲字幕av一区二区三区四区| 三级久久三级久久| 国产成人avxxxxx在线看| 亚洲免费在线视频观看| 久久久久久黄| 国产精品久久久一区| 中文字幕一区二区三区人妻四季| 免费成人美女在线观看.| 国产精品国语对白| 亚洲永久精品视频| 国产资源精品在线观看| 97人人模人人爽视频一区二区| 亚洲精品第五页| av网站一区二区三区| 久久亚洲免费| yjizz视频网站在线播放| 中文字幕一区二区三区乱码在线 | 精品国产一区二区三区久久狼黑人 | 国模无码大尺度一区二区三区| 国产噜噜噜噜噜久久久久久久久| 国产精品乱码久久久| 国产精品一区在线观看乱码| 国产伦精品一区二区三区四区免费 | 日韩大陆毛片av| 免费观看av网站| 人人狠狠综合久久亚洲婷| xx视频.9999.com| 免费在线看黄网址| 另类av一区二区| 国产精品永久在线| 亚洲AV无码精品色毛片浪潮| 成人综合在线观看| 日本精品一区二区| 菠萝蜜视频国产在线播放| 亚洲国产精品欧美一二99| 99色精品视频| 91精品一久久香蕉国产线看观看 | 欧美性猛交xxxxx水多| 欧美大尺度做爰床戏| 日本少妇精品亚洲第一区| 精品视频在线播放免| 欧美自拍偷拍网| 亚洲一级特黄| 啪一啪鲁一鲁2019在线视频| 国产精品探花视频| 94色蜜桃网一区二区三区| 亚洲人成网站在线观看播放| 午夜伦理大片视频在线观看| 色欲综合视频天天天| 一二三av在线| 国产欧美一区| 欧美精品电影在线| 中文字幕一区二区三区免费看 | 久久草.com| 免费av网站在线看| 欧美性猛交xxxx| 午夜福利三级理论电影| 精品久久久久久久久久久下田 | julia一区二区三区中文字幕| 欧美一区二区在线播放| www.久久国产| 影音先锋一区| 97人人做人人人难人人做| 国产视频三级在线观看播放| 亚洲综合色丁香婷婷六月图片| 乌克兰美女av| 岳的好大精品一区二区三区| 欧美人在线观看| 一二三区中文字幕| 久久久久99精品一区| 99热久久这里只有精品| 日韩黄色碟片| 在线看日韩av| 无码人妻丰满熟妇区bbbbxxxx| 成人精品小蝌蚪| 中文字幕人妻熟女人妻洋洋| 四虎影视国产精品| 自拍偷拍亚洲精品| 欧美视频xxxx| 久久先锋影音av鲁色资源网| 欧美 日韩 亚洲 一区| 欧美国产中文高清| 久久精品中文字幕| 91久久国语露脸精品国产高跟| 久久久久国产精品免费免费搜索 | 美女视频网站久久| 欧美日韩一区二区三区免费| 涩涩视频网站在线观看| 亚洲福利精品在线| 久久精品女人毛片国产| 国产精品一二三四五| 400部精品国偷自产在线观看| 日韩美香港a一级毛片| 中文字幕精品久久久久| 国内av在线播放| 国产精品人妖ts系列视频| www.99在线| 色婷婷亚洲mv天堂mv在影片| 国产精品一区二区在线| 美女av在线播放| 正在播放亚洲一区| 欧美日韩精品在线观看视频| 国产精品综合一区二区| 成人免费a级片| 美国成人xxx| 欧美在线视频在线播放完整版免费观看| 在线观看xxx| 在线免费观看成人短视频| 欧美人与性囗牲恔配| 青草av.久久免费一区| 一区二区三区视频| 日韩一区二区三区精品| 欧美高清不卡在线| 亚洲av电影一区| 欧美性欧美巨大黑白大战| 人人艹在线视频| 国产成人在线网站| 久久国产亚洲精品无码| 精品国产中文字幕第一页| 国产在线视频一区| 国产第一页在线视频| 亚洲毛片一区二区| 影音先锋国产在线| 一区二区三区四区激情| 亚洲少妇18p| 日韩国产精品大片| 丰满人妻一区二区三区53号 | 亚洲国产精品久久久| 你懂的国产在线| 综合久久给合久久狠狠狠97色| 国产精品嫩草69影院| 亚洲欧美日韩一区在线观看| 中文字幕日韩一区二区三区不卡| 91精品啪在线观看国产爱臀| 国产高清视频一区三区| 岛国中文字幕在线| 亚洲久久久久久久久久| 91亚洲国产成人精品一区| 亚洲一区二区视频| 日韩视频在线观看免费视频| 国产高清不卡一区二区| 一本色道无码道dvd在线观看| 亚洲综合五月| 欧美凹凸一区二区三区视频| 国产一精品一av一免费爽爽| 欧美亚洲伦理www| a毛片在线播放| 国产香蕉97碰碰久久人人| wwwav在线播放| 欧美伊人久久久久久久久影院 | 日本黄色片在线播放| 精品制服美女丁香| 国产日产欧美视频| 黑丝一区二区三区| 亚洲一区二区三区免费看| 四虎884aa成人精品最新| 亚洲精品日韩av| 国精产品一区一区三区四川| 欧美极品少妇xxxxⅹ免费视频| 日本在线免费网| 亚洲色图激情小说| 天天干在线观看| 欧美电影精品一区二区| 一区二区视频播放| 在线精品亚洲一区二区不卡| 日韩伦人妻无码| 一区二区三区中文字幕精品精品| 呻吟揉丰满对白91乃国产区| 91视频精品在这里| 欧美熟妇精品一区二区蜜桃视频| 精品综合免费视频观看| 日批视频在线免费看| 在线精品一区二区| 白白操在线视频| 亚洲人成免费网站| 7777在线视频| 久久亚洲专区| 亚洲精品中文字幕乱码三区不卡| 久久av资源| 欧美三级网色| 亚洲涩涩av| 欧美高清视频一区| 男男gay无套免费视频欧美| 久久大片网站| 国产日韩三级| 国产欧美日韩综合一区在线观看| jizz国产精品| 黄色99视频| 欧美日韩精品一区二区三区在线观看| 国产精品xxxx| 国产一级成人av| 国产欧美日本在线| 台湾色综合娱乐中文网| 久久久久久a亚洲欧洲aⅴ| 欧美巨大xxxx| 欧美成熟毛茸茸复古| 国产精品片aa在线观看| 欧美日韩大片一区二区三区| 美女精品一区最新中文字幕一区二区三区 | 伦理一区二区三区| 久久久综合亚洲91久久98| 亚洲aa在线| 日本午夜精品一区二区三区| 精品国产一区二区三区香蕉沈先生 | 自拍一级黄色片| 国产成人啪免费观看软件| 久久无码专区国产精品s| 99这里都是精品| 公侵犯人妻一区二区三区| 久久久久国产精品麻豆ai换脸| 天天干天天舔天天操| 自拍偷拍亚洲激情| 久久久久久欧美精品se一二三四| 亚洲h动漫在线| 亚洲s码欧洲m码国产av| 欧美日韩专区在线| 国产女人18毛片18精品| 亚洲成人久久网| 日本ー区在线视频| 久久精品视频网站| 九色91在线| 国产成人拍精品视频午夜网站| 欧美成人xxxx| 国产精品国产精品国产专区蜜臀ah | 久久久久久久尹人综合网亚洲| 免费黄色一级网站| 国产乱子轮精品视频| 北岛玲一区二区| 国产精品美女www爽爽爽| 久久久久久久久艹| 91黄色免费观看| 国产熟女精品视频| 精品一区二区三区三区| 拍真实国产伦偷精品| 欧美激情中文字幕在线| 激情都市亚洲| 91av免费看| 最新亚洲精品| 日本男女交配视频| 日本欧美大码aⅴ在线播放| 在线观看你懂的视频| 久久蜜桃av一区精品变态类天堂 | 免费一级毛片在线观看| 久久这里只有精品99| 小早川怜子影音先锋在线观看| 成人黄色免费在线观看| 欧美福利在线播放网址导航| 国产盗摄视频在线观看| 欧美亚洲专区| 韩国三级在线看| 国产精品污www在线观看| 激情综合网五月婷婷| 欧美美女一区二区在线观看| 人人九九精品| 久久久久久久国产精品| 国产精品国产三级在线观看| 日韩av一级大片| 亚洲黄色毛片| 中文字幕乱妇无码av在线| 久久久www成人免费毛片麻豆| 国产一级淫片免费| 制服丝袜日韩国产| 国产福利在线看| 欧美性视频在线| 高清精品视频| 日韩一级特黄毛片| 精品在线一区二区三区| 妖精视频在线观看免费| 欧美日韩在线视频一区| 国产成人手机在线| 欧美人在线视频| 精品伊人久久| 在线观看成人免费| 国内精品自线一区二区三区视频| av在线播放中文字幕| 欧美专区日韩专区| 春暖花开成人亚洲区| 日韩av电影手机在线| 女人av一区| 波多野结衣家庭教师视频| caoporm超碰国产精品| 日本三级网站在线观看| 亚洲成人激情在线观看| 牛牛精品在线| 国产精品一区二区欧美黑人喷潮水| 最新国产精品| 波多野结衣电影免费观看| 一区二区三区在线观看网站| 超碰福利在线观看| 欧美激情精品久久久久久免费印度| 国产精品日本一区二区三区在线| 中文字幕在线亚洲精品| 韩国午夜理伦三级不卡影院| 尤物在线免费视频| 日韩写真欧美这视频| 污污的网站在线免费观看| 高清不卡一区二区三区| 极品av少妇一区二区| 国产草草浮力影院| 欧美日韩亚洲一区二区| 黄色大片在线免费观看| 国产精品久久久久久久久免费看| 欧美www视频在线观看| www.51色.com| 亚洲午夜影视影院在线观看| 日韩在线视频第一页| 欧美一级大片在线观看| 精品国产中文字幕第一页| 日本黄色的视频| 一区二区三区 在线观看视频| 人成网站在线观看| 国产精品96久久久久久又黄又硬| 欧美日韩国产高清电影| 国产5g成人5g天天爽| 亚洲国产日韩在线一区模特| 午夜视频1000| 国产精品亚洲综合天堂夜夜| 91精品国产91久久久久久黑人| 最新中文字幕日本| 色综合久久久久久久久久久| 色老头视频在线观看| 91在线观看网站| 久久不射网站| 五月天婷婷色综合| 亚洲激情视频网| 久久91视频| 日本手机在线视频| 欧美国产日本韩| www香蕉视频| 国产精品99久久久久久人| 中文字幕日韩欧美精品高清在线| 国产精品成人99一区无码 | 欧美日韩国产高清电影| 爱情岛论坛亚洲自拍| 日韩欧美在线观看视频| 国产网站在线免费观看| 欧美精彩一区二区三区| 国产一区二区三区在线看麻豆| 国产高潮久久久| www.欧美精品一二三区| 牛牛影视一区二区三区免费看| 在线观看免费av网址| 欧美性xxxx在线播放| 亚洲区欧洲区| 亚洲图片小说在线| 99国产精品视频免费观看|