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

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - spring boot 1.5.4 集成shiro+cas,實(shí)現(xiàn)單點(diǎn)登錄和權(quán)限控制

spring boot 1.5.4 集成shiro+cas,實(shí)現(xiàn)單點(diǎn)登錄和權(quán)限控制

2020-11-23 11:01追極 Java教程

這篇文章主要介紹了spring boot 1.5.4 集成shiro+cas,實(shí)現(xiàn)單點(diǎn)登錄和權(quán)限控制,需要的朋友可以參考下

1.添加maven依賴(先安裝好cas-server-3.5.2,安裝步驟請(qǐng)查看本文參考文章)

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-spring</artifactId>
  <version>1.2.4</version>
</dependency>
<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-ehcache</artifactId>
  <version>1.2.4</version>
</dependency>
<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-cas</artifactId>
  <version>1.2.4</version>
</dependency>

2.啟動(dòng)累添加@ServletComponentScan注解

 
?
1
 
2
3
4
5
6
7
8
9
10
11
12
13
@SpringBootApplication
public class Application {
  /**
   * main function
   * @param args params
   */
  public static void main(String[] args){
    ConfigurableApplicationContext context = SpringApplication.run(Application.class,args);
    //test if a xml bean inject into springcontext successful
    User user = (User)context.getBean("user1");
    System.out.println(JSONObject.toJSONString(user));
  }
}

 3.配置shiro+cas

 
?
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
package com.hdwang.config.shiroCas;
import com.hdwang.dao.UserDao;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.cas.CasFilter;
import org.apache.shiro.cas.CasSubjectFactory;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.filter.DelegatingFilterProxy;
import javax.servlet.Filter;
import javax.servlet.annotation.WebListener;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
 * Created by hdwang on 2017/6/20.
 * shiro+cas 配置
 */
@Configuration
public class ShiroCasConfiguration {
  private static final Logger logger = LoggerFactory.getLogger(ShiroCasConfiguration.class);
  // cas server地址
  public static final String casServerUrlPrefix = "https://localhost:8443/cas";
  // Cas登錄頁(yè)面地址
  public static final String casLoginUrl = casServerUrlPrefix + "/login";
  // Cas登出頁(yè)面地址
  public static final String casLogoutUrl = casServerUrlPrefix + "/logout";
  // 當(dāng)前工程對(duì)外提供的服務(wù)地址
  public static final String shiroServerUrlPrefix = "http://localhost:8081";
  // casFilter UrlPattern
  public static final String casFilterUrlPattern = "/cas";
  // 登錄地址
  public static final String loginUrl = casLoginUrl + "?service=" + shiroServerUrlPrefix + casFilterUrlPattern;
  // 登出地址
  public static final String logoutUrl = casLogoutUrl+"?service="+shiroServerUrlPrefix;
  // 登錄成功地址
  public static final String loginSuccessUrl = "/home";
  // 權(quán)限認(rèn)證失敗跳轉(zhuǎn)地址
  public static final String unauthorizedUrl = "/error/403.html";
  @Bean
  public EhCacheManager getEhCacheManager() {
    EhCacheManager em = new EhCacheManager();
    em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
    return em;
  }
  @Bean(name = "myShiroCasRealm")
  public MyShiroCasRealm myShiroCasRealm(EhCacheManager cacheManager) {
    MyShiroCasRealm realm = new MyShiroCasRealm();
    realm.setCacheManager(cacheManager);
    //realm.setCasServerUrlPrefix(ShiroCasConfiguration.casServerUrlPrefix);
    // 客戶端回調(diào)地址
    //realm.setCasService(ShiroCasConfiguration.shiroServerUrlPrefix + ShiroCasConfiguration.casFilterUrlPattern);
    return realm;
  }
  /**
   * 注冊(cè)單點(diǎn)登出listener
   * @return
   */
  @Bean
  public ServletListenerRegistrationBean singleSignOutHttpSessionListener(){
    ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean();
    bean.setListener(new SingleSignOutHttpSessionListener());
//    bean.setName(""); //默認(rèn)為bean name
    bean.setEnabled(true);
    //bean.setOrder(Ordered.HIGHEST_PRECEDENCE); //設(shè)置優(yōu)先級(jí)
    return bean;
  }
  /**
   * 注冊(cè)單點(diǎn)登出filter
   * @return
   */
  @Bean
  public FilterRegistrationBean singleSignOutFilter(){
    FilterRegistrationBean bean = new FilterRegistrationBean();
    bean.setName("singleSignOutFilter");
    bean.setFilter(new SingleSignOutFilter());
    bean.addUrlPatterns("/*");
    bean.setEnabled(true);
    //bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return bean;
  }
  /**
   * 注冊(cè)DelegatingFilterProxy(Shiro)
   *
   * @return
   * @author SHANHY
   * @create 2016年1月13日
   */
  @Bean
  public FilterRegistrationBean delegatingFilterProxy() {
    FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
    filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
    // 該值缺省為false,表示生命周期由SpringApplicationContext管理,設(shè)置為true則表示由ServletContainer管理
    filterRegistration.addInitParameter("targetFilterLifecycle", "true");
    filterRegistration.setEnabled(true);
    filterRegistration.addUrlPatterns("/*");
    return filterRegistration;
  }
  @Bean(name = "lifecycleBeanPostProcessor")
  public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
    return new LifecycleBeanPostProcessor();
  }
  @Bean
  public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
    daap.setProxyTargetClass(true);
    return daap;
  }
  @Bean(name = "securityManager")
  public DefaultWebSecurityManager getDefaultWebSecurityManager(MyShiroCasRealm myShiroCasRealm) {
    DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
    dwsm.setRealm(myShiroCasRealm);
//   <!-- 用戶授權(quán)/認(rèn)證信息Cache, 采用EhCache 緩存 -->
    dwsm.setCacheManager(getEhCacheManager());
    // 指定 SubjectFactory
    dwsm.setSubjectFactory(new CasSubjectFactory());
    return dwsm;
  }
  @Bean
  public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
    AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
    aasa.setSecurityManager(securityManager);
    return aasa;
  }
  /**
   * CAS過濾器
   *
   * @return
   * @author SHANHY
   * @create 2016年1月17日
   */
  @Bean(name = "casFilter")
  public CasFilter getCasFilter() {
    CasFilter casFilter = new CasFilter();
    casFilter.setName("casFilter");
    casFilter.setEnabled(true);
    // 登錄失敗后跳轉(zhuǎn)的URL,也就是 Shiro 執(zhí)行 CasRealm 的 doGetAuthenticationInfo 方法向CasServer驗(yàn)證tiket
    casFilter.setFailureUrl(loginUrl);// 我們選擇認(rèn)證失敗后再打開登錄頁(yè)面
    return casFilter;
  }
  /**
   * ShiroFilter<br/>
   * 注意這里參數(shù)中的 StudentService 和 IScoreDao 只是一個(gè)例子,因?yàn)槲覀冊(cè)谶@里可以用這樣的方式獲取到相關(guān)訪問數(shù)據(jù)庫(kù)的對(duì)象,
   * 然后讀取數(shù)據(jù)庫(kù)相關(guān)配置,配置到 shiroFilterFactoryBean 的訪問規(guī)則中。實(shí)際項(xiàng)目中,請(qǐng)使用自己的Service來(lái)處理業(yè)務(wù)邏輯。
   *
   * @param securityManager
   * @param casFilter
   * @param userDao
   * @return
   * @author SHANHY
   * @create 2016年1月14日
   */
  @Bean(name = "shiroFilter")
  public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager, CasFilter casFilter, UserDao userDao) {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    // 必須設(shè)置 SecurityManager
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    // 如果不設(shè)置默認(rèn)會(huì)自動(dòng)尋找Web工程根目錄下的"/login.jsp"頁(yè)面
    shiroFilterFactoryBean.setLoginUrl(loginUrl);
    // 登錄成功后要跳轉(zhuǎn)的連接
    shiroFilterFactoryBean.setSuccessUrl(loginSuccessUrl);
    shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
    // 添加casFilter到shiroFilter中
    Map<String, Filter> filters = new HashMap<>();
    filters.put("casFilter", casFilter);
    // filters.put("logout",logoutFilter());
    shiroFilterFactoryBean.setFilters(filters);
    loadShiroFilterChain(shiroFilterFactoryBean, userDao);
    return shiroFilterFactoryBean;
  }
  /**
   * 加載shiroFilter權(quán)限控制規(guī)則(從數(shù)據(jù)庫(kù)讀取然后配置),角色/權(quán)限信息由MyShiroCasRealm對(duì)象提供doGetAuthorizationInfo實(shí)現(xiàn)獲取來(lái)的
   *
   * @author SHANHY
   * @create 2016年1月14日
   */
  private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean, UserDao userDao){
    /////////////////////// 下面這些規(guī)則配置最好配置到配置文件中 ///////////////////////
    Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
    // authc:該過濾器下的頁(yè)面必須登錄后才能訪問,它是Shiro內(nèi)置的一個(gè)攔截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter
    // anon: 可以理解為不攔截
    // user: 登錄了就不攔截
    // roles["admin"] 用戶擁有admin角色
    // perms["permission1"] 用戶擁有permission1權(quán)限
    // filter順序按照定義順序匹配,匹配到就驗(yàn)證,驗(yàn)證完畢結(jié)束。
    // url匹配通配符支持:? * **,分別表示匹配1個(gè),匹配0-n個(gè)(不含子路徑),匹配下級(jí)所有路徑
    //1.shiro集成cas后,首先添加該規(guī)則
    filterChainDefinitionMap.put(casFilterUrlPattern, "casFilter");
    //filterChainDefinitionMap.put("/logout","logout"); //logut請(qǐng)求采用logout filter
    //2.不攔截的請(qǐng)求
    filterChainDefinitionMap.put("/css/**","anon");
    filterChainDefinitionMap.put("/js/**","anon");
    filterChainDefinitionMap.put("/login", "anon");
    filterChainDefinitionMap.put("/logout","anon");
    filterChainDefinitionMap.put("/error","anon");
    //3.攔截的請(qǐng)求(從本地?cái)?shù)據(jù)庫(kù)獲取或者從casserver獲取(webservice,http等遠(yuǎn)程方式),看你的角色權(quán)限配置在哪里)
    filterChainDefinitionMap.put("/user", "authc"); //需要登錄
    filterChainDefinitionMap.put("/user/add/**", "authc,roles[admin]"); //需要登錄,且用戶角色為admin
    filterChainDefinitionMap.put("/user/delete/**", "authc,perms[\"user:delete\"]"); //需要登錄,且用戶有權(quán)限為user:delete
    //4.登錄過的不攔截
    filterChainDefinitionMap.put("/**", "user");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
  }
}
 
?
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
package com.hdwang.config.shiroCas;
import javax.annotation.PostConstruct;
import com.hdwang.dao.UserDao;
import com.hdwang.entity.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cas.CasRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.HashSet;
import java.util.Set;
/**
 * Created by hdwang on 2017/6/20.
 * 安全數(shù)據(jù)源
 */
public class MyShiroCasRealm extends CasRealm{
  private static final Logger logger = LoggerFactory.getLogger(MyShiroCasRealm.class);
  @Autowired
  private UserDao userDao;
  @PostConstruct
  public void initProperty(){
//   setDefaultRoles("ROLE_USER");
    setCasServerUrlPrefix(ShiroCasConfiguration.casServerUrlPrefix);
    // 客戶端回調(diào)地址
    setCasService(ShiroCasConfiguration.shiroServerUrlPrefix + ShiroCasConfiguration.casFilterUrlPattern);
  }
//  /**
//   * 1、CAS認(rèn)證 ,驗(yàn)證用戶身份
//   * 2、將用戶基本信息設(shè)置到會(huì)話中(不用了,隨時(shí)可以獲取的)
//   */
//  @Override
//  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
//
//    AuthenticationInfo authc = super.doGetAuthenticationInfo(token);
//
//    String account = (String) authc.getPrincipals().getPrimaryPrincipal();
//
//    User user = userDao.getByName(account);
//    //將用戶信息存入session中
//    SecurityUtils.getSubject().getSession().setAttribute("user", user);
//
//    return authc;
//  }
  /**
   * 權(quán)限認(rèn)證,為當(dāng)前登錄的Subject授予角色和權(quán)限
   * @see 經(jīng)測(cè)試:本例中該方法的調(diào)用時(shí)機(jī)為需授權(quán)資源被訪問時(shí)
   * @see 經(jīng)測(cè)試:并且每次訪問需授權(quán)資源時(shí)都會(huì)執(zhí)行該方法中的邏輯,這表明本例中默認(rèn)并未啟用AuthorizationCache
   * @see 經(jīng)測(cè)試:如果連續(xù)訪問同一個(gè)URL(比如刷新),該方法不會(huì)被重復(fù)調(diào)用,Shiro有一個(gè)時(shí)間間隔(也就是cache時(shí)間,在ehcache-shiro.xml中配置),超過這個(gè)時(shí)間間隔再刷新頁(yè)面,該方法會(huì)被執(zhí)行
   */
  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    logger.info("##################執(zhí)行Shiro權(quán)限認(rèn)證##################");
    //獲取當(dāng)前登錄輸入的用戶名,等價(jià)于(String) principalCollection.fromRealm(getName()).iterator().next();
    String loginName = (String)super.getAvailablePrincipal(principalCollection);
    //到數(shù)據(jù)庫(kù)查是否有此對(duì)象(1.本地查詢 2.可以遠(yuǎn)程查詢casserver 3.可以由casserver帶過來(lái)角色/權(quán)限其它信息)
    User user=userDao.getByName(loginName);// 實(shí)際項(xiàng)目中,這里可以根據(jù)實(shí)際情況做緩存,如果不做,Shiro自己也是有時(shí)間間隔機(jī)制,2分鐘內(nèi)不會(huì)重復(fù)執(zhí)行該方法
    if(user!=null){
      //權(quán)限信息對(duì)象info,用來(lái)存放查出的用戶的所有的角色(role)及權(quán)限(permission)
      SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
      //給用戶添加角色(讓shiro去驗(yàn)證)
      Set<String> roleNames = new HashSet<>();
      if(user.getName().equals("boy5")){
        roleNames.add("admin");
      }
      info.setRoles(roleNames);
      if(user.getName().equals("李四")){
        //給用戶添加權(quán)限(讓shiro去驗(yàn)證)
        info.addStringPermission("user:delete");
      }
      // 或者按下面這樣添加
      //添加一個(gè)角色,不是配置意義上的添加,而是證明該用戶擁有admin角色
//      simpleAuthorInfo.addRole("admin");
      //添加權(quán)限
//      simpleAuthorInfo.addStringPermission("admin:manage");
//      logger.info("已為用戶[mike]賦予了[admin]角色和[admin:manage]權(quán)限");
      return info;
    }
    // 返回null的話,就會(huì)導(dǎo)致任何用戶訪問被攔截的請(qǐng)求時(shí),都會(huì)自動(dòng)跳轉(zhuǎn)到unauthorizedUrl指定的地址
    return null;
  }
}
 
?
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
package com.hdwang.controller;
import com.hdwang.config.shiroCas.ShiroCasConfiguration;
import com.hdwang.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpSession;
/**
 * Created by hdwang on 2017/6/21.
 * 跳轉(zhuǎn)至cas server去登錄(一個(gè)入口)
 */
@Controller
@RequestMapping("")
public class CasLoginController {
  /**
   * 一般用不到
   * @param model
   * @return
   */
  @RequestMapping(value="/login",method= RequestMethod.GET)
  public String loginForm(Model model){
    model.addAttribute("user", new User());
//   return "login";
    return "redirect:" + ShiroCasConfiguration.loginUrl;
  }
  @RequestMapping(value = "logout", method = { RequestMethod.GET,
      RequestMethod.POST })
  public String loginout(HttpSession session)
  {
    return "redirect:"+ShiroCasConfiguration.logoutUrl;
  }
}
 
?
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
package com.hdwang.controller;
import com.alibaba.fastjson.JSONObject;
import com.hdwang.entity.User;
import com.hdwang.service.datajpa.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.SecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/**
 * Created by hdwang on 2017/6/19.
 */
@Controller
@RequestMapping("/home")
public class HomeController {
  @Autowired
  UserService userService;
  @RequestMapping("")
  public String index(HttpSession session, ModelMap map, HttpServletRequest request){
//    User user = (User) session.getAttribute("user");
    System.out.println(request.getUserPrincipal().getName());
    System.out.println(SecurityUtils.getSubject().getPrincipal());
    User loginUser = userService.getLoginUser();
    System.out.println(JSONObject.toJSONString(loginUser));
    map.put("user",loginUser);
    return "home";
  }
}

 4.運(yùn)行驗(yàn)證

登錄

訪問:http://localhost:8081/home

跳轉(zhuǎn)至:https://localhost:8443/cas/login?service=http://localhost:8081/cas

輸入正確用戶名密碼登錄跳轉(zhuǎn)回:http://localhost:8081/cas?ticket=ST-203-GUheN64mOZec9IWZSH1B-cas01.example.org

最終跳回:http://localhost:8081/home

登出

訪問:http://localhost:8081/logout

跳轉(zhuǎn)至:https://localhost:8443/cas/logout?service=http://localhost:8081

由于未登錄,又執(zhí)行登錄步驟,所以最終返回https://localhost:8443/cas/login?service=http://localhost:8081/cas

這次登錄成功后返回:http://localhost:8081/

cas server端登出(也行)

訪問:https://localhost:8443/cas/logout

再訪問:http://localhost:8081/home 會(huì)跳轉(zhuǎn)至登錄頁(yè),perfect!

以上所述是小編給大家介紹的spring boot 1.5.4 集成shiro+cas,實(shí)現(xiàn)單點(diǎn)登錄和權(quán)限控制,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)服務(wù)器之家網(wǎng)站的支持!

原文鏈接:http://www.cnblogs.com/hdwang/archive/2017/06/22/7064492.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美乱妇高清无乱码视频在线 | 日本亚洲娇小与黑人tube | 北条麻妃黑人 | 欧美娇小性xxxx | 性夜影院爽黄A爽免费动漫 性色欲情网站IWWW九文堂 | 好大好硬好深好爽想要吃奶 | 四虎影院在线免费观看视频 | 精品国产免费第一区二区三区日韩 | 攻插受 | 99久久国产综合精品女小说 | 色哟哟哟在线精品观看视频 | 成人福利在线视频免费观看 | 青青草99久久精品国产综合 | 精品一区二区三区免费站 | 嫩草在线观看视频 | 黑人与欧洲女子性大战 | 大ji巴好好爽好深网站 | 亚洲成片在线看 | 高清视频在线播放ww | 成人国产在线播放 | 丝瓜草莓香蕉绿巨人幸福宝 | 99久久免费精品视频 | 日本亚洲欧洲高清有码在线播放 | 日本一道本视频 | 亚洲国产黄色 | 日本在线观看免费高清 | 成年私人影院免费视频网站 | 猛男壮男受bl爽哭了高h | 成人尤物 | 国产精品伊人 | 情缘1完整版在线观看 | 国产精品欧美在线观看 | 美女舒服好紧太爽了视频 | 天堂资源在线8 | 国产自拍视频一区 | 亚洲激情久久 | 亚洲欧美日韩中文字幕久久 | 亚洲精品视频一区 | 国产外围 | 草莓香蕉绿巨人丝瓜榴莲污在线观看 | 窝窝影院午夜色在线视频 |