中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

政府網(wǎng)站建設(shè)被問責(zé)怎么讓網(wǎng)站快速收錄

政府網(wǎng)站建設(shè)被問責(zé),怎么讓網(wǎng)站快速收錄,海報(bào)設(shè)計(jì)在線生成,找事做的網(wǎng)站處理解析JWT時(shí)的異常 由于解析JWT是在過濾器中執(zhí)行的,而過濾器是整個(gè)服務(wù)器端中最早接收到所有請(qǐng)求的組件,此時(shí),控制器等其它組件尚未運(yùn)行,則不可以使用此前的“全局異常處理器”來處理解析JWT時(shí)的異常(全局異常處理器…

處理解析JWT時(shí)的異常

由于解析JWT是在過濾器中執(zhí)行的,而過濾器是整個(gè)服務(wù)器端中最早接收到所有請(qǐng)求的組件,此時(shí),控制器等其它組件尚未運(yùn)行,則不可以使用此前的“全局異常處理器”來處理解析JWT時(shí)的異常(全局異常處理器只能處理控制器拋出的異常),也就是說,在過濾器中只能使用try...catch語法來處理異常!

為了便于表示需要響應(yīng)到客戶端的結(jié)果,仍推薦使用JsonResult封裝相關(guān)信息,而響應(yīng)到客戶端的結(jié)果應(yīng)該是JSON格式的,則需要將JsonResult對(duì)象轉(zhuǎn)換成JSON格式的字符串!

在項(xiàng)目中添加fastjson依賴項(xiàng),此依賴項(xiàng)可以實(shí)現(xiàn)Java對(duì)象與JSON格式的字符串的相互轉(zhuǎn)換:

<!-- fastjson:實(shí)現(xiàn)對(duì)象與JSON的相互轉(zhuǎn)換 -->
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.75</version>
</dependency>

在處理異常之前,還應(yīng)該在ServiceCode中補(bǔ)充相關(guān)的業(yè)務(wù)狀態(tài)碼,例如:

ERR_JWT_EXPIRED(60000),
ERR_JWT_MALFORMED(60100),
ERR_JWT_SIGNATURE(60200),

然后,調(diào)整JwtAuthorizationFilter中解析JWT的代碼片段:

Claims claims = null;
response.setContentType("application/json; charset=utf-8");
try {claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();
} catch (SignatureException e) {String message = "非法訪問!";log.warn("解析JWT時(shí)出現(xiàn)SignatureException,響應(yīng)消息:{}", message);JsonResult<Void> jsonResult = JsonResult.fail(ServiceCode.ERR_JWT_SIGNATURE, message);PrintWriter printWriter = response.getWriter();printWriter.println(JSON.toJSONString(jsonResult));printWriter.close();return;
} catch (MalformedJwtException e) {String message = "非法訪問!";log.warn("解析JWT時(shí)出現(xiàn)MalformedJwtException,響應(yīng)消息:{}", message);JsonResult<Void> jsonResult = JsonResult.fail(ServiceCode.ERR_JWT_MALFORMED, message);PrintWriter printWriter = response.getWriter();printWriter.println(JSON.toJSONString(jsonResult));printWriter.close();return;
} catch (ExpiredJwtException e) {String message = "您的登錄信息已過期,請(qǐng)重新登錄!";log.warn("解析JWT時(shí)出現(xiàn)ExpiredJwtException,響應(yīng)消息:{}", message);JsonResult<Void> jsonResult = JsonResult.fail(ServiceCode.ERR_JWT_EXPIRED, message);PrintWriter printWriter = response.getWriter();printWriter.println(JSON.toJSONString(jsonResult));printWriter.close();return;
}

關(guān)于認(rèn)證信息中的“當(dāng)事人”

認(rèn)證信息中的“當(dāng)事人”可以通過@AuthenticationPrincipal注入到方法(控制器的方法)的參數(shù)中,在訪求處理過程中,可能需要獲取“當(dāng)事人”的ID、用戶名等數(shù)據(jù),所以,應(yīng)該自定義數(shù)據(jù)類型表示“當(dāng)事人”(Spring Security也希望你這樣做,所以,在認(rèn)證結(jié)果的信息中的“當(dāng)事人”被聲明為Object類型)!

在項(xiàng)目的根包下創(chuàng)建security.LoginPrincipal類:

package cn.tedu.csmall.passport.security;import lombok.Data;import java.io.Serializable;/*** 當(dāng)事人類型,就是成功通過認(rèn)證的用戶信息類型* * @author java@tedu.cn* @version 0.0.1*/
@Data
public class LoginPrincipal implements Serializable {/*** 當(dāng)事人ID*/private Long id;/*** 當(dāng)事人用戶名*/private String username;}

然后,調(diào)整JwtAuthorizationFilter中的相關(guān)代碼:

Long id = claims.get("id", Long.class);
String username = claims.get("username", String.class);
log.debug("從JWT中解析得到的管理員ID:{}", id);
log.debug("從JWT中解析得到的管理員用戶名:{}", username);// 基于解析JWT的結(jié)果創(chuàng)建認(rèn)證信息
LoginPrincipal principal = new LoginPrincipal();
principal.setId(id);
principal.setUsername(username);// 暫不關(guān)心其它代碼

在控制器中處理請(qǐng)求的方法的參數(shù)列表中,可以通過@AuthenticationPrincipal注入LoginPrincipal類型的參數(shù),在處理請(qǐng)求的過程中,可以通過此參數(shù)獲取當(dāng)事人的具體數(shù)據(jù):

@GetMapping("")
public JsonResult<List<AdminListItemVO>> list(//                                  ↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 自定義的當(dāng)事人類型@ApiIgnore @AuthenticationPrincipal LoginPrincipal loginPrincipal) {log.debug("開始處理【查詢管理員列表】的請(qǐng)求,參數(shù):無");log.debug("當(dāng)事人:{}", loginPrincipal);log.debug("當(dāng)事人的ID:{}", loginPrincipal.getId());log.debug("當(dāng)事人的用戶名:{}", loginPrincipal.getUsername());List<AdminListItemVO> list = adminService.list();return JsonResult.ok(list);
}

關(guān)于權(quán)限

目前,當(dāng)管理員登錄成功后,服務(wù)器端生成的JWT中并不包含此管理員的權(quán)限信息,所以,此管理員后續(xù)攜帶JWT提交請(qǐng)求時(shí),服務(wù)器端也無法根據(jù)此JWT直接獲取管理員的權(quán)限列表,更加不能把正確的權(quán)限列表存入到SecurityContext中的認(rèn)證信息中,所以,無法檢查管理員的權(quán)限!

可以在管理員登錄成功后,將此管理員的權(quán)限列表也寫入到JWT中!

**注意:**由于權(quán)限列表并不是一般的字面值數(shù)據(jù),生成到JWT中后,將無法還原回原本的集合類型!應(yīng)該先將權(quán)限列表轉(zhuǎn)換成JSON格式的字符串,后續(xù),再根據(jù)此JSON數(shù)據(jù)還原回原本的列表!

AdminServiceImpl中的login()方法中調(diào)整:

// 將通過認(rèn)證的管理員的相關(guān)信息存入到JWT中
// 準(zhǔn)備生成JWT的相關(guān)數(shù)據(jù)
Date date = new Date(System.currentTimeMillis() + durationInMinute * 60 * 1000);
AdminDetails principal = (AdminDetails) authenticationResult.getPrincipal();
Map<String, Object> claims = new HashMap<>();
claims.put("id", principal.getId());
claims.put("username", principal.getUsername());
Collection<GrantedAuthority> authorities = principal.getAuthorities(); // 新增
String authoritiesJsonString = JSON.toJSONString(authorities); // 新增
claims.put("authoritiesJsonString", authoritiesJsonString); // 新增

然后,在JwtAuthorizationFilter中調(diào)整:

Long id = claims.get("id", Long.class);
String username = claims.get("username", String.class);
String authoritiesJsonString = claims.get("authoritiesJsonString", String.class); // 新增
log.debug("從JWT中解析得到的管理員ID:{}", id);
log.debug("從JWT中解析得到的管理員用戶名:{}", username);
log.debug("從JWT中解析得到的管理員權(quán)限列表JSON:{}", authoritiesJsonString);// ========== 將原有的“山寨”權(quán)限的代碼替換為以下代碼 ==========
// 將JSON格式的權(quán)限列表轉(zhuǎn)換成Authentication需要的類型(Collection<GrantedAuthority>)
List<SimpleGrantedAuthority> authorities =JSON.parseArray(authoritiesJsonString, SimpleGrantedAuthority.class);

最后,在控制器中,可以繼續(xù)使用@PreAuthroize注解檢查權(quán)限!

**注意:**在API文檔的調(diào)試中,需要使用新的JWT數(shù)據(jù)!

關(guān)于清空SecurityContext

目前,當(dāng)使用有效的JWT提交請(qǐng)求后,即使下一次(間隔時(shí)間不能太久)不攜帶JWT再次提交請(qǐng)求,也是服務(wù)器端認(rèn)可的!

這是因?yàn)?#xff1a;當(dāng)使用有效的JWT提交請(qǐng)求后,JwtAuthorizationFilter會(huì)將此JWT中的信息創(chuàng)建為Authentication對(duì)象,并將此Authentication保存到SecurityContext中!而SecurityContext是基于Session的,所以,在Session未過期之前,即使后續(xù)的請(qǐng)求沒有攜帶JWT,Spring Security仍能從Session中找到SecurityContext中的Authentication對(duì)象,會(huì)視為此次訪問與此前的訪問是同一個(gè)客戶端。

如果認(rèn)為這是一種不合理的表現(xiàn),可以在JwtAuthorizationFilter中,在執(zhí)行過濾之初,就不由分說的**清空SecurityContext**即可!

// 清除SecurityContext中的數(shù)據(jù)
SecurityContextHolder.clearContext();

處理未登錄的錯(cuò)誤

當(dāng)客戶端沒有攜帶JWT,卻向需要通過認(rèn)證的URL發(fā)起請(qǐng)求,默認(rèn)將響應(yīng)403錯(cuò)誤,這種問題需要在Spring Security的配置類中的void configure(HttpSecurity http)方法中進(jìn)行配置:

// 處理“需要通過認(rèn)證,但是實(shí)際上未通過認(rèn)證就發(fā)起的請(qǐng)求”導(dǎo)致的錯(cuò)誤
http.exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {String message = "未檢測(cè)到登錄,請(qǐng)登錄!(在開發(fā)階段,看到此提示時(shí),請(qǐng)檢查客戶端是否攜帶了JWT向服務(wù)器端發(fā)起請(qǐng)求)";JsonResult<Void> jsonResult = JsonResult.fail(ServiceCode.ERR_UNAUTHORIZED, message);response.setContentType("application/json; charset=utf-8");PrintWriter printWriter = response.getWriter();printWriter.println(JSON.toJSONString(jsonResult));printWriter.close();}
});

關(guān)于Spring Security的認(rèn)證流程

請(qǐng)?zhí)砑訄D片描述

使用axios攜帶JWT發(fā)起請(qǐng)求

當(dāng)需要攜帶JWT發(fā)起請(qǐng)求時(shí),根據(jù)業(yè)內(nèi)慣例,JWT應(yīng)該放在請(qǐng)求頭的Authorization屬性中,則使用axios時(shí)需要自定義請(qǐng)求頭,其語法是:

// 以下調(diào)用的create()表示創(chuàng)建一個(gè)axios實(shí)例,此函數(shù)的參數(shù)是一個(gè)對(duì)象,用于表示新創(chuàng)建的axios的參數(shù)
this.axios.create({'headers': {'Authorization': jwt}}).get(); // 與此前使用相同,在此處調(diào)用get()或post()發(fā)起請(qǐng)求

關(guān)于復(fù)雜請(qǐng)求的預(yù)檢機(jī)制導(dǎo)致的跨域問題

在使用了Spring Security框架的項(xiàng)目中,當(dāng)客戶端攜帶JWT向服務(wù)器端發(fā)起異步請(qǐng)求,默認(rèn)會(huì)出現(xiàn)跨域訪問的錯(cuò)誤(即使在服務(wù)器端通過Spring MVC配置類允許跨域,此問題依然存在),可以在Spring Security的配置類中的void configure(HttpSecurity http)方法中添加配置,以解決此問題:

http.cors();

出現(xiàn)此問題的根本原因在于:如果客戶端提交的請(qǐng)求自定義了請(qǐng)求頭中的特定屬性(例如配置了請(qǐng)求頭中的Authorization屬性),此請(qǐng)求會(huì)被視為“復(fù)雜請(qǐng)求”,客戶端的瀏覽器會(huì)先向服務(wù)器端的此URL發(fā)起OPTIONS類型的請(qǐng)求執(zhí)行“預(yù)檢(PreFlight)”,如果預(yù)檢不通過,則不允許提交原本嘗試提交的請(qǐng)求。

所以,可以在Spring Security的配置類中,對(duì)所有OPTIONS類型的請(qǐng)求“放行”,即可解決此問題:

http.authorizeRequests() // 配置URL的訪問控制// 重要,以下2行代碼表示:對(duì)所有OPTIONS類型的請(qǐng)求“放行”.mvcMatchers(HttpMethod.OPTIONS, "/**").permitAll().mvcMatchers(urls).permitAll().anyRequest().authenticated();

或者,通過http.cors();也可以解決此問題,此方法的本質(zhì)是啟用了Spring Security自帶的CorsFilter過濾器,此過濾器會(huì)對(duì)OPTIONS請(qǐng)求放行。

http://m.risenshineclean.com/news/58619.html

相關(guān)文章:

  • 福州做網(wǎng)站的公seo分析工具有哪些
  • 中山哪里做網(wǎng)站seo職業(yè)培訓(xùn)班
  • 邯鄲網(wǎng)站設(shè)計(jì)招聘最新域名查詢
  • 公眾號(hào)視頻網(wǎng)站開發(fā)微博營(yíng)銷成功案例8個(gè)
  • 怎么讓網(wǎng)站欄目頁收錄廣州公司關(guān)鍵詞網(wǎng)絡(luò)推廣
  • 企業(yè)商務(wù)網(wǎng)站建設(shè)策劃書優(yōu)化網(wǎng)站首頁
  • 播視頻網(wǎng)站開發(fā)網(wǎng)站外鏈查詢
  • 做網(wǎng)站找哪家好熊掌號(hào)英文關(guān)鍵詞seo
  • 做視頻網(wǎng)站需要什么空間視頻號(hào)直播推廣二維碼
  • 微信如何做積分商城網(wǎng)站網(wǎng)站seo關(guān)鍵詞優(yōu)化排名
  • 番禺seo培訓(xùn)如何優(yōu)化關(guān)鍵詞的排名
  • wordpress交互主題揭陽seo快速排名
  • 設(shè)計(jì)門戶網(wǎng)百度seo競(jìng)價(jià)推廣是什么
  • 做b2b比較好的網(wǎng)站seo零基礎(chǔ)入門教程
  • axure做網(wǎng)站教學(xué)視頻寧海關(guān)鍵詞優(yōu)化怎么優(yōu)化
  • 杭州做企業(yè)網(wǎng)站公司seo前線
  • 織夢(mèng)網(wǎng)站需要付費(fèi)嗎百度搜首頁
  • 許昌那有做網(wǎng)站網(wǎng)頁點(diǎn)擊量統(tǒng)計(jì)
  • 廣州做網(wǎng)站最好的公司深圳seo公司排名
  • php 建設(shè)網(wǎng)站網(wǎng)站老域名跳轉(zhuǎn)到新域名
  • 哪有做企業(yè)網(wǎng)站seo關(guān)鍵詞排名優(yōu)化品牌
  • 南岸網(wǎng)站建設(shè)百度搜索引擎怎么做
  • 企業(yè)h5網(wǎng)站建設(shè)百度推廣平臺(tái)收費(fèi)標(biāo)準(zhǔn)
  • vuejs做視頻網(wǎng)站免費(fèi)加精準(zhǔn)客源
  • 濟(jì)南做網(wǎng)站優(yōu)化網(wǎng)站制作方案
  • 馬鞍山網(wǎng)站建設(shè)咨詢電艾滋病多長(zhǎng)時(shí)間能查出來
  • 網(wǎng)站的層次怎么優(yōu)化自己網(wǎng)站
  • 一簾幽夢(mèng)紫菱做的網(wǎng)站網(wǎng)站策劃方案案例
  • 做網(wǎng)站賺錢廣州seo團(tuán)隊(duì)
  • php和織夢(mèng)那個(gè)做網(wǎng)站好網(wǎng)絡(luò)推廣營(yíng)銷策劃方案