色五月色开心色婷婷色丁香,五月婷婷丁香花综合网,婷婷丁香五月激情综合在线,五月婷婷六月丁香动漫,婷婷丁香五月激情综合在线,丁香花中文字幕在线观看,播五月色五月开心五月网,开心激情综合网,狠狠色丁香婷婷综合最新地址,丁香视频在线观看,狠狠做六月爱婷婷综合av,久久激情五月丁香伊人

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營的一線實(shí)戰(zhàn)洞察。

SpringBoot整合Shiro+Redis實(shí)現(xiàn)用戶認(rèn)證授權(quán)與分布式會(huì)話方案

SpringBoot整合Shiro+Redis實(shí)現(xiàn)用戶認(rèn)證授權(quán)與分布式會(huì)話方案 SpringBootShiroRedis 整合實(shí)現(xiàn)用戶認(rèn)證授權(quán)這套組合在中小型項(xiàng)目里實(shí)在太常見了。我自己接過好幾個(gè)這類需求真要說起來踩過的坑不比寫過的代碼少。如果你正準(zhǔn)備給項(xiàng)目加一套登錄鑒權(quán)又不想直接上Spring Security那一大坨配置那Shiro配Redis確實(shí)是個(gè)非常務(wù)實(shí)的選擇。這篇文章就把我實(shí)際整合過程中的思路、配置、代碼和問題排查全部整理出來照著做可以少走很多彎路。1. 整體設(shè)計(jì)與思路拆解1.1 為什么選 Shiro 而不是 Spring Security很多剛開始做認(rèn)證授權(quán)的同學(xué)會(huì)糾結(jié)這個(gè)問題。Spring Security背靠Spring家族功能確實(shí)強(qiáng)大社區(qū)資料也多但它的學(xué)習(xí)曲線偏陡峭過濾鏈的配置邏輯也比較繞新手往往花了兩三天連登錄流程還沒跑通。Shiro的設(shè)計(jì)哲學(xué)則相反它把認(rèn)證、授權(quán)、會(huì)話管理、加密這幾個(gè)核心能力全部抽象成簡單的API概念少、上手快一個(gè)簡單的登錄校驗(yàn)只需要理解Subject、SecurityManager、Realm這三個(gè)核心組件就能跑起來。從實(shí)際項(xiàng)目角度講如果你的系統(tǒng)是標(biāo)準(zhǔn)的單體應(yīng)用用戶量在百萬以下對(duì)安全框架的要求主要是“能快速實(shí)現(xiàn)登錄、記住我、角色權(quán)限控制”那Shiro是完全夠用的。它自帶SessionManager結(jié)合Redis之后還能解決分布式場景下的會(huì)話共享問題已經(jīng)覆蓋了絕大多數(shù)業(yè)務(wù)系統(tǒng)的需求。我見過不少公司內(nèi)部的管理后臺(tái)、運(yùn)營系統(tǒng)、中小型電商后端用的都是這套方案。當(dāng)然Shiro也不是沒有缺點(diǎn)。相比Spring Security它的過濾鏈自定義能力弱一些文檔也不夠細(xì)致遇到一些偏門問題往往要靠翻源碼解決。而且Shiro的社區(qū)活躍度近年有所下降新功能迭代比較慢。選型的時(shí)候你要評(píng)估自己的團(tuán)隊(duì)情況如果大家都沒用過Shiro但熟悉Spring生態(tài)那直接上Spring Security可能反而更順如果項(xiàng)目工期緊、需求簡單或者團(tuán)隊(duì)成員已經(jīng)有Shiro經(jīng)驗(yàn)?zāi)荢hiro這套組合性價(jià)比極高。1.2 引入 Redis 解決了什么問題單機(jī)部署的時(shí)候Shiro自帶的Session管理完全夠用Session數(shù)據(jù)存在JVM內(nèi)存里登錄狀態(tài)直接保存在服務(wù)器本地??梢坏┫到y(tǒng)需要多節(jié)點(diǎn)部署或者服務(wù)重啟、發(fā)布問題就來了用戶在A節(jié)點(diǎn)登錄下次請(qǐng)求被負(fù)載均衡轉(zhuǎn)發(fā)到B節(jié)點(diǎn)B節(jié)點(diǎn)的內(nèi)存里沒有這個(gè)Session用戶就被判定為未登錄體驗(yàn)非常割裂。傳統(tǒng)的解決方案是Session黏滯讓同一個(gè)用戶的請(qǐng)求始終轉(zhuǎn)發(fā)到同一臺(tái)機(jī)器但這只能算規(guī)避節(jié)點(diǎn)故障或重啟時(shí)問題依然存在。引入Redis之后Session數(shù)據(jù)被集中存儲(chǔ)在外部緩存中所有節(jié)點(diǎn)共享同一份會(huì)話數(shù)據(jù)。用戶無論請(qǐng)求到哪個(gè)節(jié)點(diǎn)都能從Redis正確讀取登錄狀態(tài)。同時(shí)Redis的高讀寫性能讓Session的存取幾乎不影響接口響應(yīng)時(shí)間。除了存SessionRedis還承擔(dān)了權(quán)限緩存的角色。Shiro默認(rèn)每次請(qǐng)求都會(huì)執(zhí)行Realm的授權(quán)方法如果你的授權(quán)邏輯里有數(shù)據(jù)庫查詢?cè)诟卟l(fā)場景下這個(gè)開銷會(huì)被放大。把角色和權(quán)限列表緩存到Redis后同一用戶的權(quán)限校驗(yàn)直接命中緩存大幅減少了數(shù)據(jù)庫的壓力。這套設(shè)計(jì)在真正的生產(chǎn)環(huán)境里效果很明顯我有一次壓測加了Redis緩存之后QPS提升了將近30%。1.3 整體架構(gòu)與數(shù)據(jù)流轉(zhuǎn)過程這套方案的核心數(shù)據(jù)流轉(zhuǎn)可以簡單概括為請(qǐng)求進(jìn)來Shiro過濾鏈判斷是否有登錄憑證有則從Redis中取出Session恢復(fù)用戶的登錄狀態(tài)需要鑒權(quán)時(shí)從Redis緩存取出權(quán)限信息進(jìn)行校驗(yàn)登錄成功后用戶信息和Session寫入Redis退出登錄時(shí)刪除Redis中的會(huì)話數(shù)據(jù)。具體到一次登錄請(qǐng)求的時(shí)序用戶提交用戶名密碼Shiro把請(qǐng)求包裝成一個(gè)UsernamePasswordToken交給SecurityManagerSecurityManager委托給配置好的Realm去做認(rèn)證——Realm里我們寫的是先查數(shù)據(jù)庫用戶信息再用密碼加密規(guī)則比對(duì)密碼認(rèn)證成功后Shiro根據(jù)配置生成Session并存入Redis同時(shí)用戶主體信息也被緩存起來。后續(xù)每次請(qǐng)求經(jīng)過過濾鏈時(shí)Shiro的SessionDAO都會(huì)先去Redis里查這個(gè)Session是否還存在從而判斷用戶是否有效登錄。這套流程把“認(rèn)證”“會(huì)話”“緩存”三個(gè)環(huán)節(jié)通過Redis串起來結(jié)構(gòu)清晰每個(gè)環(huán)節(jié)都可以獨(dú)立做擴(kuò)展。比如后續(xù)要加“記住我”功能只要調(diào)整Cookie和Session的有效期邏輯要加多終端登錄限制也只需在Session管理上做文章。2. 核心細(xì)節(jié)解析與實(shí)操要點(diǎn)2.1 Shiro 三大核心組件的工作機(jī)制Shiro的工作模型圍繞Subject、SecurityManager、Realm展開。用生活化的類比來解釋這三者的關(guān)系Subject是“當(dāng)前操作的人”SecurityManager是“門衛(wèi)”Realm是“員工花名冊(cè)”。Subject代表當(dāng)前用戶封裝了用戶的所有安全操作。在代碼里你可以隨時(shí)通過SecurityUtils.getSubject()拿到它然后用subject.login(token)做登錄用subject.isAuthenticated()判斷是否已登錄用subject.hasRole(admin)判斷角色。它本質(zhì)上是Shiro與當(dāng)前線程綁定的一個(gè)上下文對(duì)象簡化了安全操作的調(diào)用方式。SecurityManager整個(gè)Shiro的心臟負(fù)責(zé)協(xié)調(diào)認(rèn)證、授權(quán)、會(huì)話管理等所有內(nèi)部組件。它自己不干活而是把任務(wù)分發(fā)給其他組件執(zhí)行。在SpringBoot整合時(shí)我們需要在配置類里創(chuàng)建一個(gè)SecurityManager的Bean并把它綁定到Shiro的過濾鏈上。Realm數(shù)據(jù)訪問層的橋接器Shiro通過它獲取用戶的認(rèn)證信息和授權(quán)信息。默認(rèn)的Realm什么都不做我們必須寫一個(gè)自定義Realm繼承AuthorizingRealm重寫doGetAuthenticationInfo認(rèn)證時(shí)用和doGetAuthorizationInfo授權(quán)時(shí)用這兩個(gè)方法。這是整個(gè)整合方案里最核心的代碼部分。理解這三個(gè)組件的職責(zé)邊界排起錯(cuò)來會(huì)清晰很多。比如登錄失敗問題大概率出在Realm里的認(rèn)證邏輯權(quán)限校驗(yàn)不通過就要檢查doGetAuthorizationInfo里返回的權(quán)限集合是否正確。2.2 過濾鏈配置anon、authc、roles、perms 的含義Shiro的過濾鏈?zhǔn)峭ㄟ^配置URL和對(duì)應(yīng)的過濾器來實(shí)現(xiàn)訪問控制的這也是它最讓人頭疼但又最靈活的部分。常用的幾個(gè)過濾器要搞清楚anon匿名訪問不需要登錄就可以訪問。通常用來放行登錄接口、注冊(cè)接口、靜態(tài)資源、驗(yàn)證碼接口。authc必須登錄后才能訪問。配置了authc的路徑如果用戶未登錄會(huì)被重定向到登錄頁面或返回未授權(quán)提示。roles必須擁有指定角色才能訪問。它需要參數(shù)比如roles[admin]表示只有admin角色可以訪問。perms必須擁有指定權(quán)限才能訪問同樣需要參數(shù)比如perms[user:add]。配置的順序非常重要。Shiro的過濾鏈?zhǔn)恰暗谝淮纹ヅ鋬?yōu)先”的也就是說一條請(qǐng)求在前面匹配到了anon就會(huì)立刻放行后面的authc根本不會(huì)生效。我見過有同學(xué)把/**authc配置在前面結(jié)果所有請(qǐng)求都要登錄后面配置的放行規(guī)則完全失效。正確的做法是放行規(guī)則寫前面兜底的攔截規(guī)則寫最后具體化的路徑寫前面通配的路徑寫后面。2.3 Redis 在 Shiro 整合中的兩種核心用途Redis這套方案里扮演兩個(gè)完全不同的角色很多人在配置時(shí)容易混淆導(dǎo)致出現(xiàn)一些很隱蔽的問題。第一個(gè)用途是作為Session的存儲(chǔ)介質(zhì)。Shiro把原本存在JVM的Session搬到Redis里需要我們自己實(shí)現(xiàn)一個(gè)RedisSessionDAO繼承AbstractSessionDAO重寫doCreate、doRead、doUpdate、doDelete這幾個(gè)方法。Shiro每次創(chuàng)建、讀取、更新、刪除Session時(shí)都會(huì)調(diào)用這個(gè)DAO。寫入Redis的key我們通常設(shè)計(jì)成shiro_session_xxx這樣的格式value是序列化后的Session對(duì)象。第二個(gè)用途是權(quán)限數(shù)據(jù)的緩存。Shiro的Realm里有一個(gè)AuthorizationCache默認(rèn)內(nèi)存實(shí)現(xiàn)。我們把它替換成RedisCache實(shí)現(xiàn)后用戶權(quán)限信息會(huì)以shiro_cache_xxx的key形式存入Redis緩存有效期可以單獨(dú)設(shè)置。兩種數(shù)據(jù)雖然都放在Redis里但生命周期和用途不一樣建議在Redis的key前綴上做明確區(qū)分避免相互干擾。2.4 序列化方案Java 序列化 vs JSON 序列化把Session對(duì)象和權(quán)限對(duì)象存入Redis之前必須經(jīng)過序列化。這里有個(gè)很多人踩過的坑RedisTemplate默認(rèn)的序列化器是JdkSerializationRedisSerializer它要求存儲(chǔ)的對(duì)象必須實(shí)現(xiàn)Serializable接口。如果你的用戶實(shí)體類沒實(shí)現(xiàn)Serializable運(yùn)行時(shí)就會(huì)拋序列化異常。用Java原生序列化雖然簡單但存儲(chǔ)的內(nèi)容可讀性極差全是亂碼和類路徑信息占用空間也大。更推薦的做法是用FastJson或Jackson做序列化這樣Redis里看到的是清晰的JSON結(jié)構(gòu)排查問題時(shí)一眼就能看出存儲(chǔ)的內(nèi)容。不過要注意用JSON序列化時(shí)從Redis讀出來的對(duì)象是JSON反序列化后的副本不是原來的對(duì)象引用在極端情況下可能存在數(shù)據(jù)一致性問題。考慮到Session和權(quán)限信息通常是只讀使用這個(gè)權(quán)衡是可以接受的。我在生產(chǎn)環(huán)境里用的是改造過的RedisSessionDAO內(nèi)部統(tǒng)一走JSON序列化這樣Redis里的數(shù)據(jù)鍵值對(duì)一目了然出了問題的定位效率高很多。3. 實(shí)操過程與核心環(huán)節(jié)實(shí)現(xiàn)3.1 Maven 依賴引入首先在pom.xml里引入必要的依賴。我用的版本組合是經(jīng)過實(shí)際驗(yàn)證的可以直接抄dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.apache.shiro/groupId artifactIdshiro-spring-boot-starter/artifactId version1.9.1/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId /dependency dependency groupIdorg.apache.commons/groupId artifactIdcommons-pool2/artifactId /dependency dependency groupIdcom.alibaba/groupId artifactIdfastjson/artifactId version2.0.26/version /dependency需要注意shiro-spring-boot-starter這個(gè)依賴在不同版本下的兼容性差異挺明顯。如果你用的是Spring Boot 2.x建議Shiro版本選1.8.x以上1.9.x更穩(wěn)如果你是Spring Boot 3.x那要特別注意Shiro對(duì)Jakarta命名空間的支持問題最好找專門的適配版本。3.2 自定義Realm實(shí)現(xiàn)認(rèn)證與授權(quán)自定義Realm是整套方案的核心代碼。我習(xí)慣創(chuàng)建一個(gè)名為UserRealm的類繼承AuthorizingRealm里面實(shí)現(xiàn)認(rèn)證和授權(quán)兩個(gè)方法。先看認(rèn)證方法Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken usernamePasswordToken (UsernamePasswordToken) token; String username usernamePasswordToken.getUsername(); // 根據(jù)用戶名查詢數(shù)據(jù)庫 User user userService.findByUsername(username); if (user null) { throw new UnknownAccountException(用戶不存在); } if (user.getStatus() 0) { throw new LockedAccountException(賬號(hào)已被鎖定); } // 返回認(rèn)證信息密碼的比對(duì)由CredentialsMatcher完成 return new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes(user.getSalt()), getName()); }注意這里有個(gè)關(guān)鍵設(shè)計(jì)我沒有在Realm里手動(dòng)比對(duì)密碼而是把數(shù)據(jù)庫查出的加密密碼返回給Shiro由配置的CredentialsMatcher去自動(dòng)比對(duì)。這樣做的好處是密碼校驗(yàn)邏輯集中管理后續(xù)如果更換加密算法只需要替換Matcher的實(shí)現(xiàn)不影響Realm的其它邏輯。再看授權(quán)方法Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { User user (User) principals.getPrimaryPrincipal(); SimpleAuthorizationInfo info new SimpleAuthorizationInfo(); // 查詢用戶角色 SetString roles roleService.findRolesByUserId(user.getId()); // 查詢用戶權(quán)限 SetString perms permissionService.findPermsByUserId(user.getId()); info.setRoles(roles); info.setStringPermissions(perms); return info; }這個(gè)方法的調(diào)用時(shí)機(jī)很特殊不是每次請(qǐng)求都會(huì)執(zhí)行而是首次訪問需要角色或權(quán)限校驗(yàn)的接口時(shí)才觸發(fā)而且結(jié)果會(huì)被緩存。所以把權(quán)限查詢邏輯寫在這里非常合適配合Redis緩存可以大幅減少數(shù)據(jù)庫查詢。3.3 Shiro 核心配置類編寫配置類負(fù)責(zé)把Realm、SecurityManager、SessionDAO、過濾鏈全部串起來。我直接給出一個(gè)可以運(yùn)行的配置骨架Configuration public class ShiroConfig { Bean public UserRealm userRealm() { return new UserRealm(); } Bean public SecurityManager securityManager(UserRealm userRealm, RedisSessionDAO sessionDAO) { DefaultWebSecurityManager manager new DefaultWebSecurityManager(); manager.setRealm(userRealm); manager.setSessionManager(sessionManager(sessionDAO)); // 開啟Redis緩存權(quán)限數(shù)據(jù) manager.setCacheManager(redisCacheManager()); return manager; } Bean public SessionManager sessionManager(RedisSessionDAO sessionDAO) { DefaultWebSessionManager sessionManager new DefaultWebSessionManager(); sessionManager.setSessionDAO(sessionDAO); // Session有效期單位毫秒這里設(shè)置為2小時(shí) sessionManager.setGlobalSessionTimeout(7200000); return sessionManager; } Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { ShiroFilterFactoryBean factoryBean new ShiroFilterFactoryBean(); factoryBean.setSecurityManager(securityManager); // 登錄接口 factoryBean.setLoginUrl(/api/login); // 未授權(quán)跳轉(zhuǎn)地址 factoryBean.setUnauthorizedUrl(/api/unauthorized); // 過濾鏈配置 MapString, String filterChainDefinitionMap new LinkedHashMap(); // 放行登錄、注冊(cè)、驗(yàn)證碼接口 filterChainDefinitionMap.put(/api/login, anon); filterChainDefinitionMap.put(/api/register, anon); filterChainDefinitionMap.put(/api/captcha, anon); // 靜態(tài)資源放行 filterChainDefinitionMap.put(/static/**, anon); // 用戶相關(guān)接口需要登錄 filterChainDefinitionMap.put(/api/user/**, authc); // 管理員接口需要admin角色 filterChainDefinitionMap.put(/api/admin/**, roles[admin]); // 增加權(quán)限示例 filterChainDefinitionMap.put(/api/user/add, perms[user:add]); // 其余接口需要登錄 filterChainDefinitionMap.put(/**, authc); factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return factoryBean; } }有一處細(xì)節(jié)要提醒filterChainDefinitionMap的類型一定是LinkedHashMap保證有序性。如果用了HashMap過濾鏈的匹配順序會(huì)變得不可預(yù)測表面上看著配置沒問題實(shí)際跑起來卻會(huì)出現(xiàn)各種奇怪的訪問異常。另外CacheManager的Redis實(shí)現(xiàn)需要我們自己寫一個(gè)類繼承AbstractCacheManager創(chuàng)建RedisCache。這個(gè)類的代碼量不大核心是把Cache接口的get、put、remove方法映射到Redis的讀寫刪除操作上。3.4 RedisSessionDAO 與 RedisCache 實(shí)現(xiàn)這部分是整合過程中的硬骨頭直接給出可用的核心實(shí)現(xiàn)。RedisSessionDAO繼承AbstractSessionDAO關(guān)鍵是序列化方式。我選擇用FastJson處理先把Session轉(zhuǎn)成JSON字符串存入Redis讀取時(shí)再反序列化。還有一個(gè)細(xì)節(jié)是key的過期時(shí)間設(shè)置——Session本身有超時(shí)時(shí)間Redis的key也要設(shè)置一個(gè)對(duì)應(yīng)的TTL防止Session永久殘留在Redis里變成臟數(shù)據(jù)。Component public class RedisSessionDAO extends AbstractSessionDAO { Autowired private RedisTemplateString, String redisTemplate; private static final String SESSION_KEY_PREFIX shiro_session:; private static final long SESSION_TIMEOUT 7200L; Override protected Serializable doCreate(Session session) { Serializable sessionId generateSessionId(session); assignSessionId(session, sessionId); saveSession(session); return sessionId; } Override protected Session doReadSession(Serializable sessionId) { String key SESSION_KEY_PREFIX sessionId; String sessionStr redisTemplate.opsForValue().get(key); if (sessionStr null) { return null; } return JSON.parseObject(sessionStr, SimpleSession.class); } private void saveSession(Session session) { String key SESSION_KEY_PREFIX session.getId(); String sessionStr JSON.toJSONString(session); redisTemplate.opsForValue().set(key, sessionStr, SESSION_TIMEOUT, TimeUnit.SECONDS); } Override public void update(Session session) throws UnknownSessionException { saveSession(session); } Override public void delete(Session session) { String key SESSION_KEY_PREFIX session.getId(); redisTemplate.delete(key); } }RedisCache的實(shí)現(xiàn)稍微復(fù)雜主要是把緩存key映射到Redis key并統(tǒng)一管理過期時(shí)間。這里我直接用一個(gè)StringRedisTemplate操作避免序列化器不一致帶來的問題。3.5 登錄接口與退出登錄的實(shí)現(xiàn)登錄接口的邏輯很直觀核心就兩行代碼創(chuàng)建token調(diào)用subject.login。PostMapping(/login) public Result login(RequestBody LoginRequest loginRequest) { Subject subject SecurityUtils.getSubject(); UsernamePasswordToken token new UsernamePasswordToken( loginRequest.getUsername(), loginRequest.getPassword() ); try { subject.login(token); // 登錄成功后可以從subject里拿到用戶信息 User user (User) subject.getPrincipal(); return Result.success(登錄成功, user); } catch (UnknownAccountException e) { return Result.error(用戶不存在); } catch (IncorrectCredentialsException e) { return Result.error(密碼錯(cuò)誤); } catch (LockedAccountException e) { return Result.error(賬號(hào)被鎖定); } catch (AuthenticationException e) { return Result.error(認(rèn)證失敗); } }退出登錄更簡單一行代碼GetMapping(/logout) public Result logout() { Subject subject SecurityUtils.getSubject(); subject.logout(); return Result.success(退出成功); }調(diào)用subject.logout()之后Shiro會(huì)清掉當(dāng)前Subject的身份信息并通過我們實(shí)現(xiàn)的RedisSessionDAO刪除對(duì)應(yīng)的Session數(shù)據(jù)。從Redis里檢查一下key對(duì)應(yīng)的數(shù)據(jù)是否被清掉就能確認(rèn)退出邏輯是否生效。3.6 權(quán)限注解的使用方式除了過濾鏈配置Shiro還支持在接口方法上使用注解來控制權(quán)限粒度更細(xì)用起來也比URL配置更清晰。RestController RequestMapping(/api/user) public class UserController { // 需要登錄才能訪問 RequiresAuthentication GetMapping(/info) public Result getUserInfo() { User user (User) SecurityUtils.getSubject().getPrincipal(); return Result.success(user); } // 需要admin角色 RequiresRoles(admin) PostMapping(/delete) public Result deleteUser(RequestParam Long userId) { userService.deleteById(userId); return Result.success(刪除成功); } // 需要user:add權(quán)限 RequiresPermissions(user:add) PostMapping(/add) public Result addUser(RequestBody User user) { userService.add(user); return Result.success(新增成功); } }使用注解方式有個(gè)先決條件必須在配置類里開啟Shiro注解支持并且確保Shiro的攔截器配置了可代理的目標(biāo)對(duì)象。Spring Boot整合Shiro后默認(rèn)會(huì)通過AOP方式支持注解但需要額外加入一個(gè)Bean配置讓Spring的切面能夠攔截到這些注解。3.7 密碼加密方案的選型與實(shí)現(xiàn)密碼安全是整個(gè)認(rèn)證系統(tǒng)里絕對(duì)不能含糊的部分。早期很多系統(tǒng)直接用MD5存密碼這在如今的安全環(huán)境下是遠(yuǎn)遠(yuǎn)不夠的。我推薦使用MD5加隨機(jī)鹽的方式甚至直接用BCrypt成本低效果好。以MD5加鹽為例注冊(cè)時(shí)生成一個(gè)隨機(jī)salt密碼加密的邏輯如下// 生成隨機(jī)鹽 String salt RandomStringUtils.randomAlphanumeric(8); // 加密迭代次數(shù)可以根據(jù)需要調(diào)整 String encryptedPassword new Md5Hash(rawPassword, salt, 2).toHex();數(shù)據(jù)庫里存儲(chǔ)的是加密后的密碼和鹽。登錄時(shí)Shiro會(huì)通過CredentialsMatcher進(jìn)行密碼比對(duì)我們要在ShiroConfig的UserRealm里設(shè)置對(duì)應(yīng)的MatcherBean public UserRealm userRealm() { UserRealm realm new UserRealm(); // 使用帶鹽的MD5迭代2次 HashedCredentialsMatcher matcher new HashedCredentialsMatcher(); matcher.setHashAlgorithmName(MD5); matcher.setHashIterations(2); realm.setCredentialsMatcher(matcher); return realm; }這里面有一處非常容易踩坑HashedCredentialsMatcher默認(rèn)認(rèn)為數(shù)據(jù)庫里存儲(chǔ)的密碼是Hex字符串如果當(dāng)時(shí)加密用的是Base64或者其他編碼比對(duì)就會(huì)一直失敗。所以注冊(cè)時(shí)的編碼方式和Matcher的預(yù)期必須嚴(yán)格一致改起來很費(fèi)勁。如果要從根本上提高安全性可以直接用BCrypt。BCrypt的哈希自帶鹽不需要額外字段存salt校驗(yàn)時(shí)直接用BCrypt.matches(rawPassword, encryptedPassword)即可。Shiro也有對(duì)應(yīng)的BCryptCredentialsMatcher可以配置。代價(jià)是BCrypt的計(jì)算開銷大一些但對(duì)登錄這種低頻操作來說完全不是問題。4. 整合過程中的常見問題與排查實(shí)錄4.1 Session 失效或每次請(qǐng)求都重新登錄這個(gè)問題的典型表現(xiàn)是前端調(diào)用登錄接口成功了但下一次請(qǐng)求就被過濾鏈攔截判定為未登錄。排查思路先檢查Redis里面有沒有寫入Session數(shù)據(jù)。如果Redis里根本沒有shiro_session開頭的key說明SessionDAO的寫入邏輯沒有被執(zhí)行或執(zhí)行失敗。常見原因有幾種RedisTemplate的序列化配置有問題Session對(duì)象寫入Redis時(shí)報(bào)序列化異常被Shiro內(nèi)部吞掉了。SessionDAO沒有正確注入到SessionManagerShiro還是用的默認(rèn)內(nèi)存Session實(shí)現(xiàn)。檢查配置里sessionManager的setSessionDAO是否真的生效。Cookie的名稱或路徑不對(duì)瀏覽器沒有保存Shiro生成的SessionID。用瀏覽器的開發(fā)者工具看一下請(qǐng)求Cookie的情況。如果是前端部署在另外一個(gè)域名的場景還要考慮Cookie跨域的問題。Shiro默認(rèn)的Cookie只在同域名下有效跨域時(shí)需要配置Cookie的domain屬性或者改成前后端分離模式前端手動(dòng)攜帶SessionID。4.2 密碼一直匹配不上的問題密碼比對(duì)失敗的排查核心是注冊(cè)時(shí)的加密邏輯和登錄時(shí)的校驗(yàn)邏輯必須完全一致。最常見的坑是加鹽方式不對(duì)。注冊(cè)時(shí)用new Md5Hash(password, salt, 2)但登錄時(shí)Matcher拿到的ByteSource如果不一致結(jié)果必然不一樣。在Realm里返回AuthenticationInfo時(shí)鹽的構(gòu)造方式必須和注冊(cè)時(shí)保持一致。比如注冊(cè)時(shí)用的是隨機(jī)字符串salt那么Realm返回時(shí)也要用ByteSource.Util.bytes(user.getSalt())。另外一個(gè)坑是迭代次數(shù)。我遇到過一個(gè)情況數(shù)據(jù)庫表里有歷史數(shù)據(jù)老數(shù)據(jù)的迭代次數(shù)是1次新數(shù)據(jù)是2次結(jié)果老用戶全部登錄失敗。解決思路是漸進(jìn)式遷移登錄成功后檢測當(dāng)前用戶的加密參數(shù)如果是老版本在登錄成功的同時(shí)用新參數(shù)重新加密一遍密碼并更新數(shù)據(jù)庫。4.3 Redis 緩存導(dǎo)致權(quán)限變更不生效這是最容易讓人困惑的問題之一。管理員在后臺(tái)修改了某個(gè)用戶的角色或者權(quán)限但該用戶下次訪問接口時(shí)還是舊權(quán)限甚至需要重啟服務(wù)才生效。原因是權(quán)限信息被緩存到了Redis而且是按用戶維度緩存的。只要不主動(dòng)清理Redis中的緩存會(huì)一直沿用舊數(shù)據(jù)。解決思路有三種在權(quán)限變更的接口里主動(dòng)清理對(duì)應(yīng)用戶權(quán)限的緩存。需要拿到權(quán)限緩存Manager調(diào)用clearCache方法。給權(quán)限緩存設(shè)置較短的過期時(shí)間比如30分鐘犧牲一些性能換取準(zhǔn)實(shí)時(shí)性。在權(quán)限變更后強(qiáng)制該用戶重新登錄通過登錄流程重建權(quán)限緩存。實(shí)際項(xiàng)目里我比較推薦第一種思路在業(yè)務(wù)代碼里預(yù)留緩存清理邏輯。雖然要多寫一點(diǎn)代碼但權(quán)限變更的響應(yīng)是幾乎實(shí)時(shí)的運(yùn)營和管理同事的體驗(yàn)會(huì)好很多。4.4 RedisSessionDAO 反序列化報(bào)錯(cuò)這種情況在Session數(shù)據(jù)是舊版本寫入、代碼升級(jí)后重新讀取時(shí)容易發(fā)生。比如之前用Java原生序列化寫入的Session代碼改成JSON序列化后舊的Redis數(shù)據(jù)還在新代碼嘗試用JSON解析直接拋異常。解決思路是平滑升級(jí)改代碼之前先把Redis里的Session數(shù)據(jù)一次性清掉。發(fā)布時(shí)設(shè)置session的有效期短一些讓舊Session盡快過期。更好的方案是代碼里做兼容處理讀數(shù)據(jù)失敗時(shí)catch異常并返回null讓Shiro對(duì)這個(gè)Session重新走創(chuàng)建流程。4.5 權(quán)限注解不生效的排查在Spring Boot項(xiàng)目里啟用Shiro注解需要確認(rèn)兩個(gè)方面一是自定義Realm的Bean必須被Spring管理二是Shiro的注解掃描需要開啟。常見的配置是引入一個(gè)AuthorizationAttributeSourceAdvisor的Bean它的作用是把Shiro的注解和Spring AOP關(guān)聯(lián)起來。如果配置了還是不生效優(yōu)先檢查是不是類沒有被Spring掃描到或者接口方法用了private修飾。Shiro的注解是通過AOP代理實(shí)現(xiàn)的private方法是不會(huì)走代理的所以注解必須放在public方法上。5. 這個(gè)方案的擴(kuò)展與優(yōu)化方向5.1 基于 Redis 的限流與防刷既然Redis已經(jīng)集成進(jìn)來了順手加一個(gè)接口防刷的機(jī)制是很自然的擴(kuò)展。在登錄接口上做限制比如同一個(gè)IP一分鐘內(nèi)最多嘗試5次登錄超過則直接拒絕。實(shí)現(xiàn)也不復(fù)雜用Redis的INCR和EXPIRE命令就能搞定。String key login:limit: ipAddress; Long count redisTemplate.opsForValue().increment(key); if (count ! null count 1) { redisTemplate.expire(key, 1, TimeUnit.MINUTES); } if (count ! null count 5) { throw new RuntimeException(登錄嘗試次數(shù)過多請(qǐng)稍后再試); }這個(gè)邏輯放在登錄接口的最前面攔截效果非常直接。它也是目前很多互聯(lián)網(wǎng)產(chǎn)品在用的登錄防暴力破解手段。5.2 記住我功能與退出策略Shiro自帶RememberMe功能開啟后用戶關(guān)閉瀏覽器SessionId仍然保存在本地Cookie中下次訪問自動(dòng)恢復(fù)登錄狀態(tài)。Redis的引入讓RememberMe的實(shí)現(xiàn)更有優(yōu)勢(shì)因?yàn)镾ession數(shù)據(jù)在Redis里即使用戶換了節(jié)點(diǎn)只要Cookie中的SessionId還在依然能正確恢復(fù)登錄狀態(tài)。實(shí)現(xiàn)RememberMe需要在登錄時(shí)設(shè)置token的rememberMe屬性為true并在SecurityManager中配置一個(gè)rememberMeManager把Cookie的有效期調(diào)長。要注意的是RememberMe狀態(tài)下subject.isAuthenticated()為false但subject.isRemembered()為true。如果你的代碼里用isAuthenticated()做判斷未真正登錄就拒絕訪問的接口需要特別注意這個(gè)細(xì)節(jié)。5.3 集群環(huán)境下的多節(jié)點(diǎn)會(huì)話一致性這套方案在集群環(huán)境下的表現(xiàn)是比較理想的。因?yàn)樗蠸ession數(shù)據(jù)都存在Redis每個(gè)節(jié)點(diǎn)讀到的都是同一份數(shù)據(jù)天然解決了會(huì)話一致性的問題。唯一要注意的是多個(gè)節(jié)點(diǎn)共享同一個(gè)Redis時(shí)序列化配置必須一致否則A節(jié)點(diǎn)寫入的數(shù)據(jù)會(huì)被B節(jié)點(diǎn)反序列化失敗。另一個(gè)要考慮的點(diǎn)是Redis的持久化策略要對(duì)齊公司的運(yùn)維規(guī)范。如果Redis是純緩存模式、允許數(shù)據(jù)丟失那么Redis重啟后所有用戶會(huì)集體掉線必須重新登錄。如果希望高可用可以開啟Redis的持久化或者用主從模式哨兵。這塊屬于運(yùn)維范疇但在方案設(shè)計(jì)階段就應(yīng)該想清楚免得后面上線時(shí)出大問題。6. 實(shí)操心得總結(jié)這套SpringBootShiroRedis的方案我從第一次接觸到今天前前后后在好幾個(gè)項(xiàng)目里落地過。回過頭來看最核心的收獲是技術(shù)選型一定要結(jié)合團(tuán)隊(duì)的實(shí)際能力和項(xiàng)目的真實(shí)規(guī)模不要為了炫技去選一個(gè)用不上的框架。Shiro在中小型項(xiàng)目里依然是非常能打的方案搭配Redis之后的分布式會(huì)話能力完全夠用。而且它最大的優(yōu)勢(shì)在于概念直觀新同學(xué)上手速度快出現(xiàn)問題后定位路徑非常短。相比Spring Security同樣的功能在Shiro里的實(shí)現(xiàn)代碼量大概能少30%到40%這在項(xiàng)目周期緊的時(shí)候是實(shí)打?qū)嵉膬?yōu)勢(shì)。有一點(diǎn)我覺得值得養(yǎng)成習(xí)慣正式上線前一定要對(duì)認(rèn)證授權(quán)模塊做一次專門的測試重點(diǎn)覆蓋Session過期、權(quán)限變更、多節(jié)點(diǎn)切換、并發(fā)登錄這幾個(gè)場景。這些邊角問題在單機(jī)開發(fā)和測試環(huán)境里很難暴露但一旦上了生產(chǎn)用戶報(bào)障的往往就是這類問題。最后再分享一個(gè)排查小技巧如果你在整合過程中碰到了詭異的Session、權(quán)限問題第一步永遠(yuǎn)是去Redis里看看數(shù)據(jù)是什么樣的。數(shù)據(jù)在問題就在讀數(shù)據(jù)的環(huán)節(jié)數(shù)據(jù)不在問題就在寫數(shù)據(jù)的環(huán)節(jié)。這比反復(fù)看代碼猜原因高效得多。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
一区二区精品日韩欧美在线观看 | 豆1无夜无码| 亚洲国产午夜真人一级片中文字幕精品黄网站 | 亚洲色图欧美色图制服诱惑| 伊人青青一区成人视频在线观看区| 欧美黄片免费在线观看视频| 综合伊人激情| 久久一区二区三区四区五区| 91热色| 东北夫妻性偷拍| 无码精品蜜桃一区二区三区ww| 91美女网站| 大香蕉懂9| 校园春色宗合网| 久久发布国产伦子伦精品| 久久男女激情视频网站| 精品一区二区人妖| 一,爱啪啪,在线免费视频| 国产极品粉嫩馒头一线天av| 综合亚洲欧美精品日韩?v| 午夜啊啊| 色综合大香蕉| 久久久久久久9| 色约约一区=区三区| 欧美成人综合| 色 亚洲 91| 日韩啪啪啪视频| 色诱中文字幕| 操b网站亚洲无码| 久久久久久大| 都市激情人妻一区二区青青操视频| 色呦呦、国产精品| 久久99国产综合精品女同| 丁香五月天堂网| 日韩中文字幕二区| 九九碰九九爱97超碰| 久久久网站| 一块操欧美性爱| 亚洲国产高清福利视频| 日本日皮视频逼| 搡老女人老妇女AAA一VU麻豆| 中文字幕精品免费一区二区| 亚洲图片激情综合另类| 日本护士高潮| 欧美亚综合色图| 久久久久久性爱视频| 今日头条成人一区二区三区四虎精品| 久久久不卡区一区二区三区久久久| 嗯嗯啊好大| 亚洲天堂电影网| 日韩AV噜噜噜一区二区三区四区 | 国产视频一区二区三区在线免费观看 | 99re超碰| 国产一区二区三区高清视频| 日韩免费三级黄片电影| 18禁美女裸体无遮挡啪啪| 一级久久性爱视频| 色色色热| 老熟女熟妇| 大鸡吧尹人在线| 日韩99神马视频播放片在线播放| 色九九综合AV| 日日骚av| 国产亚洲精品农村妇女| 久久综合九九| 午夜后入| 国产精品久久aV| 伊人精品久久网站| 久久色激情一区二区三区| 欧洲射精91| 亚州男人的天堂| 亚洲Av诱惑| αⅴ天堂| 99久久这里只有精品| 大香蕉啪啪啪啪在线| 天天综合~91| 欧美亚洲色图另类国产| 五月综合久久| 日韩精品三级片长长久久| a啊啊啊啊啊啊啊啊一区二区| 97欧美视频| 无色无码| 亚洲天堂情色| 亚洲人妻在线精品| 国产成人精品亚洲日本| 超碰欧美在线欧美| 天天看精品动漫视频一区| 国产人妻天天干精品| 麻豆AV96熟妇人妻| 啪啪啪亚欧美视频| 顶级丝袜熟女一区二区三区| 中文字幕88av在线| 国产 日韩,欧美 自拍| 操逼视频免费日韩无码| 婷婷精品国产一区二区三区日韩| 成人精品在线免费视频| 男人的天堂2010| 欧美黑人极品高潮喷吹熟女黑人性暴力日韩在线欧美极品一区二区老师 | 久久久人体| 美女诱惑在线一区| 波多野结衣之双飞调教在线播放| 九九热精品| 日本新免费二区三区| 亚洲美女AV无码| 99精品久久久久久久婷婷蜜桃| a人欧美综合天堂麻豆| 欧美97网| 五月丁香激情综合| 97国产|免费| 操逼片中文| 久久曰曰| 日本东京热加勒比久久| 日韩激情视频| 亚洲国产欧美一区二区潘金莲| 欧美激情视频一区二区三区不卡| 亚洲性网| 国产传媒1234区| 国产美女在线精品免费看| 亚洲男人bt天堂| 大逼色网站| 色99视频| 午夜传煤十二区精品| 日韩性爱电影一区| 亚洲伊人青青草| 亚洲第一无码播放立川理惠| 啊啊啊慢点| 无码在线亚洲| 欧美激情精品| 久久本道| 免费久久一级毛片大黄| 美女干逼2| 日本操逼二区| 日日爽熟女| 国产大学生高潮在线播放| 日本黄色天堂| 9久久精品| 天天综合网视频91| 日本丝袜美腿人妻九九| 看日韩操逼| 亚洲九九视频| 午夜福利久久久噜久噜久久综合| 一区二区精品日韩欧美在线观看| 综合大香蕉美。| 亚洲不卡AV在线| 亚洲中文字幕熟女| 嫩草91| 人人扣人人操| 99久久久无码国产精品性啊聊| 99国产精品在线观看| 亚洲AV成人无码一二三久久| 97视频新免费| 欧美色三级片91| 亚洲成人性爱网站在线播放| 精品无码久久| 久久国语| 精品一区二区三区蜜桃臀赵总| 男女无套 免费网站| 色网在线| 亚洲宅男天堂| 日韩国产乱子伦App| 色色97爱| 亚洲性猛交| 久久久久免费少妇| AV不卡在线| 亚洲熟女人妻中文字幕一区二区| 97在线青| 人妻精品4K4K4K4K4| 黄片免费看黄片免费看| 伊人热综合| 国产精品夜夜夜| 欧美色图天堂网m| 欧美强奸一区二区诱惑| 亚洲无码免费看| 啪啪性爱免费视频| 亚洲a色| 亚洲日本天堂| a人片中文字幕一区二区| 久久久婷婷| 三级色综合| 青青草好吊色| 欧美精品,四区。五区| 中文字幕天天操| 天天爱天天韩国日本牛牛牛牛 | 吉田爱美AV在线| 亚洲欧美中文日韩视频中国语| 日韩偷拍一区二区三区| 丝袜AV一区二区三区| 91视频综合在线| 91 国产丝袜在线放观看| 婷婷九月色| 人人操人人叉人人插人人| 1769一区| 日韩欧美性吧婷婷乱伦大香蕉| 久久精品成人一区二区三区蜜臀| 天天综合亚洲综合| 久久在肏| 97超碰欧美中文字幕| 亚洲好色人妻| 天操天操夜操夜月月年年操操| 欧美永久激情一区二区| 日han少妇无码| 黑操B| 大香蕉伊人久久| 特级丰满少妇一级AAAA爱毛片| 一道α片欧美| 精品人妻一区二区视频| 8x福利精品第一福利视频导航 | 欧美精品偷拍| 91精产一区二区三区| 啊啊啊啊二区好大| 天天天天做夜夜夜夜做| 欧美成人一区二区| 加勒比色综合| 不卡人妻少妇精品毛片一区23区视频| 男女性无套 免费九一| 水澄无码AV| av在线资源| 欧美男人天堂| 97网站在线观看| 欧美亚洲天堂| 超碰成人国产| 亚洲第一二区另类图| 五月天精品| 美国精品国产精品| 国产亚洲深夜激情| JULIA人妻风俗店中出电影| 18一区二区三区| 国产精品亚洲四五区在线观看| 韩日男人的天堂| 亚洲天堂第一页| 超碰午夜| av天堂电影网| 一区二区三区亚洲| 91free福利| 一区二区三区精品黑丝白丝酒店对鸡| 哈哈操电影AV| 欧美日韩国产色五月综合在线| 日韩欧美麻豆| 韩日色费| av资源在线播放天堂| 色婷婷电影网| 操死我了嗯嗯嗯| 人妻 欧美亚洲| 久夜操| 日本道不卡| 麻豆综合一区av| 午夜福利精品| 二区熟妇韩日| 精品久久久久久久| 国产日逼视频| 久久极品伊人| 日韩少妇在线视频| 无码人妻精品酒店| 国产成人无码高清| 成人网欧美风情| 亚洲在线观看| 都市久久精品激情亚洲| 青青草视频久久| 天堂伊人久久| 一区在线精品中文字幕| 五月天啪啪| 精品乱码久久久久| 久久超碰网| 色综合久久88色综合久久天天| 先锋精品av色鲁| 国产精品久久久久久久久久久久久久久久| 九九九精品美女| 黄色电影在线播放综合网站| 2020视频1区2区3区| 97在线观看免费视频l| 少妇久久久久久久久| 免费超碰97在线观看| sss视频华人在线| 黄页网站成人免费| 少妇xx精品| 嗯~啊~快点 死我视频| 久热这里| 欧美成人性爱视频大全| 亚洲综合贴图91| 在免费jIzzjIzz在线视频| 亚洲色图欧美色图制服丝袜| 欧美精品97| 性爱1区| 久久9999| 图片区小说区| 日韩大香蕉AV影片| 婷婷伊人| JuliaAnn丝袜熟女系列| 日本大片日本一区二区免费高清| 国产日韩中文字幕欧美| 爱做久久久久久| 色欧洲97| 图片区小说区| 黑人性欧美| 婷婷丁香六月| 午夜九九九九九九| 67914亚洲精品| 91丝袜视频在线观看| 久久露脸国产老熟女| 精品十八在线观看| 欧美色偷拍 | 亚洲情色电影网| 亚洲天堂一二| 91视频国品一二三区| 亚洲黄色电影| 久久精彩视频9| 91肉丝| 偷窥自拍亚洲色图| 欧美黄色片在线播放| 精品小视频在线| 亚洲一曲日韩精品| 国产精品白丝AV| 中文字幕在线观看丝袜| 伊人热综合| 久久av色| 激情久久av一区av二区av| 清纯唯美综合亚洲| 青青草十区九区爱夜| 嫩呦国产一区二区三区AV| 久热久| www久| 国产91福利小视频在线观看| 国内操逼视频二区| 亚洲宅男天堂| 国产女人和拘做爰视频| 96一区二区三区| 手机不卡视频不卡在线一二三区 | 日韩pv中文| 日韩中文字幕国产| 色97干| 国产美女91视频| 你想操日本小逼吗| 成年人黄色| 亚洲第一二区另类图| 日韩一级欧美一级在线观看| 五月亭亭六月丁香| 精品9999| 亚洲色图20p| 五月婷婷性爱| 欧美91视频| JuliaAnnXXX888| 久久蜜桃综合网| 自拍偷拍2025在线观看| 秋霞成人一级在线观看| 国产农村妇女精品| 亚洲中文字幕av| 97超碰久| 夜夜夜夜夜夜夜夜夜狠狠狠狠狠狠狠 | 欧美精品日韩久久久九| 欧美影院一区二区三区| 久久风骚城市| 北京美女一区二区| 97在线免费看| 99色热| AV网站高清无码在线观看| 久草在线| 欧美在线天堂| 欧美碰碰综合色| 久久亚洲天堂| 欧美日韩人妻婷婷一区| 男人干美女| 亚欧精品久久久久久久久久久| A V视频日本| 欧美牲| 亚洲 欧美 色图| 久热99999| 青青草精品| 九一亚洲国产免费| 欧美九9 9 9| 天天干人妇| 嫩草 人人网精品| 欧美1727免费观看视频| 久久激情视频| 天天日夜夜爽| 丁香激情五月| 久热久| 久久久国产三级黄色片| 久久xx| 久热9| 日本肏逼视频在线观看| 久久99午夜精品一区人妻| 国产精品久久久久久照片| 日韩免费高清大片在线| 人人操 欧美| 国产成人拍国产亚洲精品| 久久精品一区二区| 97久久超碰| 女人天堂av在线播放| 国产97在线 | 亚洲| 这里都是精品| 国产精品操| 亚洲天天操| 亚洲国产精品成人久久蜜臀| 一二三区操逼国产91| 9999久久久| 国产又粗又大硬免费色网视频| 1769成人国产精品视频| 亚洲巨爆乳一区二区三区四季网| 激情小说日韩无码| 懂色av色欲av蜜臀av| 日本东京热加勒比久久| A片三级无码| 屌逼麻豆| 麻豆天美传媒在线视频天堂| 欧洲精品网| 99色在线| 人人搞人人插人人操| 国产隔壁老王影院在线| 中文字幕亚洲在线一区| 美女高潮视频91| 色拍偷亚洲| 亚洲丨在线| 久久久少妇| 国产欧美精选自拍一区| 天天干天天干天天干| 亚洲日韩av一区二区三区百合| 欧美精品双插| 亚洲欧洲日韩中文字幕一区| 亚欧色图在线激情| 立川理惠无码一区二区| 亚洲情色1区| 亚洲综合一| 欧美性夜| 在线中文字幕极品av| 国内毛片无码一级毛片| 国产精品久久久九九九| 欧美色图91| 亚洲天堂一区二区久久| 99ri在线视频| 成人黄页| 亚洲成a人v欧美综合天堂下载| 成人一道本免费视频| 久久香蕉影院| 精品一二三区女同| 乱操乱伦AV| 91粉嫩萝控精品福利网站_精品影音先锋国 | 久久免费老司机精品| 欧美第一页| aaa亚无码专区| 中文字幕日本久久| 亚洲一区二区专区-国产丝袜精品丝袜-成人AV| 欲色综合| 亚洲欧美一区二区三区一猛片| 色欧美天天| 成人精品水蜜桃久久久久久久| 国产自制av蜜乳| 国产成人网站在线观看| 日日日骚女人精品| 一级成人性爱| 裸模AV女优| 2019天天干| 九九99精品| 男女性扦B| 日韩亚洲精品一区二区| 天天综和| 高清国产精品福利网站| 精品视频日日夜夜| 激情小说亚洲| 日韩免费人妻色情网站| 亚洲风情在线观看| 丁香五月天堂网| 久久成人东京热人妻| 日韩欧美午夜视频在线| 91精品久久久久久77777| 爱爱动态120秒| 中国少妇啪啪视频| 天天肏夜夜肏| 久久在肏| 精品久久青青草| 97天天日| 男人的天堂成人的社区| 国产成人91一区二区三区| 久久精品视-一级做a爰片性色毛片16美国-中国女与老外在线精品 | 色香综合| 美女露胸露尿口| 超碰成人人人爽人人爽| 毛片17S| 日本高清免费一本视频在线观看| 国产夫妻一区二区| 变态乱伦伪娘灌肠一区二区| 激情人妻另类| 欧美成va视频网站| 九九九九九精品视频| 伊人五月天| 中文字幕一区二区三区50路| 香一区二区三区| 天天影视色香欲综合网小说| 欧美中文狠| 日韩性爱电影一区| 熟女少妇视频| 校园春色亚洲欧洲| 青娱乐国产精品| 国产久9| 色五月婷婷麻豆在| 人人性爱视频免费| 色臀aV| 色一情一乱一乱一区91Av| 超碰色图| 夜夜嗷嗷一区二区| 亚洲最大AV网| 久操免费在线| 四虎影视永久在线观看精品免费网站 | 人妻嗯啊啊在线播放| 亚洲春色一区二区三区| 久欲AV| 国产人妻精品久久久一区二区三区 | 尤物视频新赏网鲜网色诱网| 大香蕉伊人网WWWn0n| 操操逼操操逼操操逼逼| 啊啊啊啊操死我| 91天天c| 激情五月婷婷| 久久黄色性爱视频| 淫荡网址| 青青青草原| 有码人妻系列| 九九99精品| 18禁中文字幕| 欧美黄色手机在线观看| 欧美性第1页| 日本不卡二三区| 色婷婷激情| 十八岁啪啪视频免费看| aaa亚无码专区| 丰满少妇精品一区二区| 九九拍拍精品视频在线播放 | 九九av| 好淫网一二三视区| www.夜夜操| 人妻日日干| 欧美精品宗合| 天美传媒婬乱在| 久久成人网站| 91欧美性| 超碰538| 九九九久千久久激情蜜桃在线看 | 国产午夜精品一区二区三区牛牛| 精吧天堂| 任你干在线视频| 超碰色老头| 久久久免费视频18| 高清肉丝中文无码| 精品一区二区三区四区外站 | 亚洲熟女综合一区二区| 欧美日韩色| 天天久久久久久| 少好三P| 丰满人妻一区二区中文| 久久精品夜色国产亚洲AV| 日本精品88888888| 97综合在线观看| 精品一区二区啪啪啪| 欧美色婷婷| 一块操欧美| 国产AV超爽| 丝袜熟女一区二区三区| 99久久久er直播网址| 久久综合国产精品国产| 无码人妻一区二区三区色欲aⅴ | 激情综合婷婷| 欧美激情五月天| 九九碰九九爱97| 9 9精品一区二区三区| 色婷婷综合网站| 色激情五月天| 蜜桃视频精品一区二区| 人妻日日夜夜精品| 亚洲大色堂| 亚洲Av噜噜一区二区三区妖精| 欧美视频激情久久久久久| 日欧毛片久久| 欧美天天在线| 一区二区视频在看| 欧美亚洲中文| 亚洲图片激情综合另类| 国产精品免费日韩| 亚洲日本韩国在线| 激情丁香五月| 大香蕉在线86| 本道在线| 欧美精品三级黄片| 在线岛国新天堂8| AV网站高清无码在线观看| 日本中文字幕在线视频| 美女黄色一级A视频| 麻豆天美国美国产| 小骚逼被操的爽不爽| 操死我了啊啊啊| 丰满人妻-区二区三区| 欧美激情激情xxxx欧美专区| 无码丰满熟妇一区二区浪潮AV| 亚洲一区二区三区AV无码| 欧美色图天堂在线| 蜜桃精品视频一区| 久久有码视频| 青草草免费网站av| 97色在线| 精品久久大胆人体| 麻豆视频一区二区| 乱欲一区二区| 久久国色天香香蕉| 日本最新1区2区3区| 69精品| 中文字幕精品一区二区精| caorenqi shipin| 欧美人妻中出| 91精品人| 天天色播| 老司机免费视频在线91| 色噜噜狠狠色综无码久久合欧美| 超碰人妻天天干| 超碰97爽| 蜜臀99久久精品久久久久久| 亚欧性爱无码| 91国产丝袜足交精品视频| 干美女人妻| 秋霞一级A片黄色视频| 开心五月婷婷| 热热色综合网| 少妇一区二区三区高速| 九九九九88| 9Ⅰ超碰| 亚洲无码?第一页| 99在线观看无大码| av网站在线看| 天天摸,夜夜摸| 久久久三区二区一区| 97资源视频| 欧美三级一级| 97综合久久| 天天拍天天操| 人妻丰满熟妇av无码区蜜桃| 成人三级片无码| 亚洲精品蜜桃久久久久久久| 色视频蜜乳| 国产日本熟女顶级一区二区三区视频| 91操熟女视频| 天美传媒av在线| 亚洲一卡二卡在线免费| 日韩一999精品| 日本精品一区二区三区四区的功能| 国产无套粉嫩白浆在| 99re在线精品78| 强奸乱伦AV网站| 国产丰满熟夫69mpp| 日韩欧美福利视频看看| 人人妻人人操人人乐| 久久久97| 亚洲国产剧情少妇激情| 一个人免费视频观看在线WWW | 97超碰公开| 91九九| 亚洲色图久久精品蜜| 国产一级137片内射麻豆| 日韩一级特黄av毛片| 嗯嗯啊啊好疼| 亚洲一区二区三区播放在线| 久久久111| 中文字幕久热视频在线| 神马影院午夜福利久久久| 制度丝袜99| 后入福利视频| 日韩免费性爱视频在线观看| 97在线/亚洲| 五月婷婷六月丁香| 日本在线观看网址| 日韩午夜国产| 国产精品色片一区二区| 伊人宅男大香蕉| 女人爽到高潮久久久| 免费精品无码一级毛片牛牛影视| 亚洲AO在线| 日韩操逼HD| 久久精品女同亚洲女同13| 久久精品99| 九九九九精品| 日韩资源网| 91超级碰| 自拍偷拍第26| 超碰到97情色| 超碰97欧美在线| 操操逼视频| 91九色丰满高潮| 四虎影库国产精品免费| 中文字幕乱在线伦视频中文字幕乱码在线 | 中文字幕国产| 94色色电影网| 人妻酒店出差被中出免费在线播放| 日本熟妇人妻中出视频| 国产97在线视频| 天天日美女的B| 五月天婷婷成人网| 波多野结衣一级视频| 综合网少妇| 久久综合女优| 99久热| 欧美综合娱乐久久| 午夜精品久久99蜜桃的功能章节| 超碰地址97| www.狠狠干.coom | 啊啊啊啊啊啊啊国| 精品伊人久久久大香线蕉小说| 91美女在线观看| 亚洲系列欧美| 欧洲乱码视频| 色五月婷婷麻豆在| 精品v日韩欧美国产| 国产h小视频在线观看免费| 97免费视频在线观看视频| 欧美激情亚洲色图| 激情五月婷| 国产精品一级片在线看| 超碰97人人cao| 欧美78P| 国产精品69久久久久孕妇欧美 | 欧美牲| 青青草一区二区高清无码视频| 人妻大相焦在线| 91色综| 狠狠操狠狠爱| 亚洲福利中文字幕在线| 色婷婷激一区二区三区 | 91xingse| 日日夜夜天天| 99碰碰| 搞中出视频在线观看| 欧美78p| 狠狠操狠狠插| 亚洲操逼网| 国产自偷自拍一区| 干婷婷综合网| 国产av美女被艹的乱叫| 国产美女mm131爽爽爽爽| 国产又猛又粗又爽又黄| 强奸抽插av| 国产精品久久久吖| 国产v亚洲v日韩v欧美v片另类| 91精品人妻| 日韩有码中文字幕女同性恋 | 日韩无码嘿咻黑热久| 大香蕉亚洲中文| 亚州色图第三区| 韩日精品四区| 啊啊啊好爽快点啊啊啊嗯嗯| 玖玖视频在线资源一区二区三区| 久久xx| 人妻激情偷乱视频一区二区三区 | 伊人久久大香蕉线AV五月天| 亚洲妇色| 国产精品亚洲日韩骚欢乐谷最新地址发布页huanieguty性屋娱乐妖精视频 | 97色操| 偷拍盗拍亚洲色图图片| 精品一区二区三区麻豆| 人人操人人色网| 欧美片第一页| 亚洲自拍天堂| 国产福利影视| 五月婷婷综合网| 国产久久久9999| 91在线色| 舔舔啊| 校园春色亚洲色图| 日本欧美中文字幕| 操逼天美3区| 曰韩成人免费视频| 四虎AV在线观看| 亚洲射综合网| 久久色AV线| 鸥美中出| 国产成人精品必看| 久久AV无码网址| 志村玲子视频一区二区| 91殴美大片| 国产AV天美传媒一区二区三区 | 日日夜夜噜| 色偷偷2020免费视频播放| 乱人乱色一区二区三区免费| 啊啊啊想要| www亚洲免费| 五月婷色| 淫骚熟女一区二区三区| 91模特在线观看| 视频一区二区免费在线| 另类 日韩 熟女| 香蕉在线一区二区三区| 色制服丝袜夫妻av一区| 易易A毛视频| 午夜视频久久久久一区| 性色av婷婷久久一区二区点复制| 青青青国产| 中文熟女五十乱码在线| 水多多映视AV| 国产av美女被艹的乱叫| 九九玖玖精品| 好湿好紧视频| 国产精品无码av| 久久久com| 精久久久| 人人玩人人添人人澡免费| 婷婷九月| 日韩精彩视频| 日本一区二区三区免费观看| 激情小说五月天| 麻豆区久久久久亚| 欧美日韩*字幕一区| 色噜噜狠狠色综无码久久合欧美| 久久久禁| 98人妻精品一区二区色欲| 99无码视频| 欧美人妻一区二区| 大黄片做爱的大的| 素人美腿视频网站| 国产精品视频在线观看| 精品一啪| 亚洲第一二区另类图| 午夜毛片亚洲精品片国产久久久| 破苞ⅩXXX性无码动漫无码| 伊人国产视频| 一级性爱视频免费在线| 亚洲欧美啪啪| 天堂无码精品国产久| 精品一区二区三区四区女| 欧美性天天| 国产原创自拍| 性一级黄色录像片网站导航| 免费一级视频特黄色大片| 超碰在97| 强奸国产精品视频| 精品一久久久| 亚洲精品国产熟女久久久久久| 一区=区三区视频| 天天看天天日天天操| 920日本午夜免费| 97亚洲在线| 天天综合色| 2020中文字幕在线观看| 99性爱视频| 亚州综合色| 天天色悠悠激情| 激情综合网亚洲| 青青草吊丝| 影音先锋每日最新资源在线观看| 91精品人妻一区二区三区蜜桃臀| 性夜影院爽黄A爽免费动漫| 蜜桃久久久久久久| 美女操逼A A| 日本欧美色| 久久黄色视频一区二区三区| 欧美日韩青操| 亚洲中文字母在线播放| 97网站在线观看| 懂色AV一区二区三区| 九九AV| 日韩国产十八禁| 亚洲三区视频| 欧美一区二区三熟女剧情| 色九区| 欧美高清第一页| 久久成年精品| 九月丁香综合网| 蜜汁欧美| 久久精品免费| 欧美经典一区二区三区| 性欧美第一页| 加勒比无码一区二区三区| a片久久久久久久久久久久| 美美91成人国产精品欧美精品久久久久久久| 99re国产精品视频| 啊啊啊啊嗯嗯在线久久久| 亚洲天堂人妻一区二区| 美女视频尤物网在线看| 国产中文字幕在线观看| 超碰超碰95| 成全在线观看免费观看| 欧美啪啪天堂| 97欧美精品综合| 日本一区二区做爱的视频| 午夜一区| 欧美综合 站| 男人的天堂2010| 日韩性爱视频在线免费观看 | 国产精品盗摄 偷窥盗摄| 国产丝袜高跟美女av免费观看| 可以看的av| 亚洲国产精品有声| 91精品国产一区三一| 日本新免费二区三区| 国产少妇肉丝在线观看| 亚洲精品一二区| 亚洲人妻久久| 午夜福利一区二区三区四区五区色婷婷| 亚州精人品大香蕉| 亚洲国产一级精品毛一级精品看免费视频 | 欧美性爱一区二区三区| 久久久久78| 久久极品一区二区| 免费簧片在线观看| 国产午夜精品理论片a大结局| 欧美在线|亚洲| 97激情97激情| 婷婷五月天福利| japan日本高清乱xxxx| 婷婷超| 久久久久久人体| 插入粉嫩少妇视频| 精品无吗久久| 91oumei| 国产精品国产拍高清AV| 久久天天艹| 在线视频亚洲无码| 色97干| 蜜臀中文无码午夜| 东北操逼| 欧洲精品网| 97亚洲资源| 一二三四免费视频| 亚洲丁香花色| 91精品伊人久久久大香线蕉91| 人人贴人人摸| 日韩激情无码影院| 无码不卡亚洲成?人片| 91中文字幕制服丝袜免费视频| 日本最新1区2区3区| 九九英色视频| 嗯嗯啊啊用力视频免费| juliaann精品熟女一区| 欧美图片偷拍| 亚洲精品男人的天堂| 婷婷色影院| 精品国产久热在线观看| 亚洲少妇中文字幕网址| 日本高清一区二区在线| 欧美日韩在线国产在线| 干干干天天| 最新的亚洲无吗| 狼狼色丁香久久婷婷综合五月| 国产女人高潮嗷嗷嗷叫小说 | 久热久一区二区三区| 天天日老熟妇| 国产人伦精品一区二区三区| 91美女在线精品视频| 久九九九九九九热| 亚洲欧美综合色| 有码色中文字幕在线观看| 黄呦呦在线| 超碰1997| 久久超碰天天| 亚洲中文字幕一区二区| 亚洲风情在线观看| 久久久久97| 中国农村熟妇毛片视频| 午夜视频黄| 亚洲欧美在线观看免费| 国语av最新自产拍在线观看| 去干网最新版| 激情丁香五月| 亚洲男人天堂网久久| 色天堂综合| 蜜桃狠狠色伊人亚洲综合 | 囯戸精品高潮呻吟旡码| 噜噜噜在线视频| 操屄不卡视频| 天美精品av| 黄色高清久久无码依人| 好吊爽好吊爽在线视频,中文字幕精品一区二区日本,国产良妇出轨视频在线观看, | 久久久久少妇| 国产成人无码a| 亚洲最大网站av| 麻豆天美国美国产AV| 99re95| 精品国产乱码久久久久久免费| 亚洲色图欧美| 亚洲 日本 国产 综合| 亚洲成av人片色午夜乱码| 久久久久性熟视频| 日韩精品一区,二区 九九...老司机| 欧美视频在线视频免费va| 东京热激情视频一二三区| 骚逼一区二区| 99少妇| 操婢日韩| 五月丁香婷婷啪啪| 人妻爽爽啪视频| 久久精品电影在线| 无码精品久久久天天影视| 九九热在线精品视频| 丝袜天堂| 啊啊啊啊免费视频| 国产精品亚洲无码| 人妻AV 中文字幕的| 97超碰巨乳| 久久久久久久精| 亚洲成人福利电影免费| 97在线免费看| 97中文字幕一区| 九九视频黄色片| 91丨九色丨东北熟女| 亚洲色香| 九九九免费视频| 日本三级R| 亚洲免费97免费| 91中文字幕| 超碰人人超在线观看| 国产美女口爆吞精| 久久老女人| 久久精品三级影视| 99re99视频在线免费观看| 亚洲av青草久久一区二区| 精品亚洲国产成人AV制服丝袜 | 操操操日本的逼| 久久国产精品91| 久久精品国产99久久,亚洲日韩久久日本一区一区三区 | 操逼1区| 综合网亚| 久久一区二区三区四区五区| 五月丁香色色网| 天堂网 主播 亚洲| 欧美精品23| xxx亚洲午夜天堂| 美女诱惑久久| 丁香五月电影| 少妇精品久久久八区九区| 国产成人无码a| 免费9 1久久| 亚洲啪啪综合?v一区综合精品区| 91中文在线| 岛国天天午夜影院传媒网| 91人妻中文| 97超视频在线观看| 久久精品国产AV一区二区三区| 91女人的网站| 欧美日韩中文视频播放| 99∨VTV| 亚洲精品91| 九九成人视频| 亚洲 欧美综合| 丁香五月AV| 男人的天堂99| 五月色综合| 精品对白久久不卡| 亚洲有薄码区日本系列中文字幕| 上特色A在线| 久久精品视-一级做a爰片性色毛片16美国-中国女与老外在线精品 | 天堂精品在线| 在线视频 亚洲精品| 国产性刺激| 国产精品成人无码a v毛片| 99热这里只有是精品10| 国产一区二区三区导航| 限制级中的三级片中的黑粗大屌屌日人妻熟女| 久久高清欧美国产| 日韩91网| 国产丝袜美女诱惑| 日本高清免费一本视频在线观看| 黄资源| 久久久久久AV无码免费网站| 人妻熟女一区二区三区视频| 色性综合| 综合国产影视三级| 日本高清加勒比| 97精品综合久久| 熟妇乱伦一区二区| 伊人伊人LD| 成人国产精品三级A片| 精品国产乱子伦一区二区三区,精品一| 夜夜爽爽爽| 高潮毛片无遮挡高清免费| 亚洲欧美日韩中文久久自慰| 色香蕉影院| 国产亚洲99久久精品熟| 日韩精品电影| 天天色播| 男女做爰猛烈动高潮A片免费应用 少妇厨房愉情理伦片bd在线观看 不卡中文字幕aⅴ在线 | 青娱乐国产剧情av一区| 亚洲限制级| 色婷婷99| 少妇一级婬片免费放一级a性色.| 久久久久96| 精品人妻二区三区| 丁香五月综合| 久久久九九九| 久久国产999| 人人妻人人操人人乐| 国产Aα| 久 久无码人妻AV| 欧美综合 站| 99re这里只有精品中心播放| 操高情无码| 久久精品熟女亚洲AV麻豆软件| 久久少妇人妻| 性欧美另类高清| 日本一区二区不卡精品| 婷婷色综合欧美日韩| 日韩国产九九精品一区二区三区毛片| 91蜜臀熟女| 操逼逼无码| 蜜乳AV.COM| 色妺妺AⅤ| ...日韩成人一区二区三区字幕| 亚洲一区中文字幕久久,果冻传媒一区二区天美传媒 | 久久久com| 上海一级黄片| 综合伊人网12色| 超碰97国产欧美| 久久成人午夜狠狠| 伊人久久国产免费观看视频| 九九久久综合| 午夜福利在线合集| 超碰精品国产无码| 搡老女人老熟女91老熟女综合网| 久久久久久久久久久久欧美日| 日本不卡高清免v欧美日韩在线观看| 成人黑料社久久| 欧美人与性动交a美精品| 日韩免费中文字幕视频| 日日躁夜夜躁狠狠躁超爽| 啊啊啊啊啊舒服| 欧美 日韩 婷婷 五月| 久久a久久| 曰韩精品九九无码 | 久久久999| 97干在线视频| 超碰九九| 97人人色| 热热色国产一二区AV| 男人精品天堂一区| 激情欧美日韩女同久久| 用力操死我| 抽查国产福利主播| 亚洲色堂免费视频| 欧洲天天在线| 欧美有码激情视频一区二区三区| 亚洲色久| av九九| 色色亚洲| 殴美牲| 九九热男人天堂| 97亚洲一区| 色老汉色| 亚洲熟妇无码一区二区三区| 一区二区三区日韩欧美| 桃色六月天| 欧美熟妇操操视频| 熟女一区二区三区| 极品久久久久久久久久久久久久| 9 7超碰在线免费观看| 亚洲日韩青青草色月| 色一射色一射| 99久久久无码| 97精品国产97久久久久久| 色婷婷小说| 久久激情视频| 欧美日韩色图片| 亚洲s在线观看| 国精综合一二三区影视| 亚洲国产综合久久久性感熟妇| 欧洲亚洲人人爽爽视频| 人妻熟女一区二区三区视频| 久久久久熟女| 日本欧美中文字幕|