您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“如何用SpringSecurity查看登錄”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“如何用SpringSecurity查看登錄”吧!
Authentication 這個接口前面和大家聊過多次,今天還要再來聊一聊。
Authentication 接口用來保存我們的登錄用戶信息,實際上,它是對主體(java.security.Principal)做了進(jìn)一步的封裝。
我們來看下 Authentication 的一個定義:
public interface Authentication extends Principal, Serializable { Collection<? extends GrantedAuthority> getAuthorities(); Object getCredentials(); Object getDetails(); Object getPrincipal(); boolean isAuthenticated(); void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException; }
接口的解釋如下:
鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)
getAuthorities 方法用來獲取用戶的權(quán)限。
getCredentials 方法用來獲取用戶憑證,一般來說就是密碼。
getDetails 方法用來獲取用戶攜帶的詳細(xì)信息,可能是當(dāng)前請求之類的東西。
getPrincipal 方法用來獲取當(dāng)前用戶,可能是一個用戶名,也可能是一個用戶對象。
isAuthenticated 當(dāng)前用戶是否認(rèn)證成功。
這里有一個比較好玩的方法,叫做 getDetails。關(guān)于這個方法,源碼的解釋如下:
Stores additional details about the authentication request. These might be an IP address, certificate serial number etc.
從這段解釋中,我們可以看出,該方法實際上就是用來存儲有關(guān)身份認(rèn)證的其他信息的,例如 IP 地址、證書信息等等。
實際上,在默認(rèn)情況下,這里存儲的就是用戶登錄的 IP 地址和 sessionId。我們從源碼角度來看下。
松哥的 SpringSecurity 系列已經(jīng)寫到第 12 篇了,看了前面的文章,相信大家已經(jīng)明白用戶登錄必經(jīng)的一個過濾器就是 UsernamePasswordAuthenticationFilter,在該類的 attemptAuthentication 方法中,對請求參數(shù)做提取,在 attemptAuthentication 方法中,會調(diào)用到一個方法,就是 setDetails。
我們一起來看下 setDetails 方法:
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) { authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); }
UsernamePasswordAuthenticationToken 是 Authentication 的具體實現(xiàn),所以這里實際上就是在設(shè)置 details,至于 details 的值,則是通過 authenticationDetailsSource 來構(gòu)建的,我們來看下:
public class WebAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> { public WebAuthenticationDetails buildDetails(HttpServletRequest context) { return new WebAuthenticationDetails(context); } } public class WebAuthenticationDetails implements Serializable { private final String remoteAddress; private final String sessionId; public WebAuthenticationDetails(HttpServletRequest request) { this.remoteAddress = request.getRemoteAddr(); HttpSession session = request.getSession(false); this.sessionId = (session != null) ? session.getId() : null; } //省略其他方法 }
默認(rèn)通過 WebAuthenticationDetailsSource 來構(gòu)建 WebAuthenticationDetails,并將結(jié)果設(shè)置到 Authentication 的 details 屬性中去。而 WebAuthenticationDetails 中定義的屬性,大家看一下基本上就明白,這就是保存了用戶登錄地址和 sessionId。
那么看到這里,大家基本上就明白了,用戶登錄的 IP 地址實際上我們可以直接從 WebAuthenticationDetails 中獲取到。
我舉一個簡單例子,例如我們登錄成功后,可以通過如下方式隨時隨地拿到用戶 IP:
@Service public class HelloService { public void hello() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); WebAuthenticationDetails details = (WebAuthenticationDetails) authentication.getDetails(); System.out.println(details); } }
這個獲取過程之所以放在 service 來做,就是為了演示隨時隨地這個特性。然后我們在 controller 中調(diào)用該方法,當(dāng)訪問接口時,可以看到如下日志:
WebAuthenticationDetails@fffc7f0c: RemoteIpAddress: 127.0.0.1; SessionId: 303C7F254DF8B86667A2B20AA0667160
可以看到,用戶的 IP 地址和 SessionId 都給出來了。這兩個屬性在 WebAuthenticationDetails 中都有對應(yīng)的 get 方法,也可以單獨獲取屬性值。
當(dāng)然,WebAuthenticationDetails 也可以自己定制,因為默認(rèn)它只提供了 IP 和 sessionid 兩個信息,如果我們想保存關(guān)于 Http 請求的更多信息,就可以通過自定義 WebAuthenticationDetails 來實現(xiàn)。
如果我們要定制 WebAuthenticationDetails,還要連同 WebAuthenticationDetailsSource 一起重新定義。
結(jié)合上篇文章的驗證碼登錄,我跟大家演示一個自定義 WebAuthenticationDetails 的例子。
上篇文章我們是在 MyAuthenticationProvider 類中進(jìn)行驗證碼判斷的,回顧一下上篇文章的代碼:
public class MyAuthenticationProvider extends DaoAuthenticationProvider { @Override protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String code = req.getParameter("code"); String verify_code = (String) req.getSession().getAttribute("verify_code"); if (code == null || verify_code == null || !code.equals(verify_code)) { throw new AuthenticationServiceException("驗證碼錯誤"); } super.additionalAuthenticationChecks(userDetails, authentication); } }
不過這個驗證操作,我們也可以放在自定義的 WebAuthenticationDetails 中來做,我們定義如下兩個類:
public class MyWebAuthenticationDetails extends WebAuthenticationDetails { private boolean isPassed; public MyWebAuthenticationDetails(HttpServletRequest req) { super(req); String code = req.getParameter("code"); String verify_code = (String) req.getSession().getAttribute("verify_code"); if (code != null && verify_code != null && code.equals(verify_code)) { isPassed = true; } } public boolean isPassed() { return isPassed; } } @Component public class MyWebAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest,MyWebAuthenticationDetails> { @Override public MyWebAuthenticationDetails buildDetails(HttpServletRequest context) { return new MyWebAuthenticationDetails(context); } }
首先我們定義 MyWebAuthenticationDetails,由于它的構(gòu)造方法中,剛好就提供了 HttpServletRequest 對象,所以我們可以直接利用該對象進(jìn)行驗證碼判斷,并將判斷結(jié)果交給 isPassed 變量保存。如果我們想擴(kuò)展屬性,只需要在 MyWebAuthenticationDetails 中再去定義更多屬性,然后從 HttpServletRequest 中提取出來設(shè)置給對應(yīng)的屬性即可,這樣,在登錄成功后就可以隨時隨地獲取這些屬性了。
最后在 MyWebAuthenticationDetailsSource 中構(gòu)造 MyWebAuthenticationDetails 并返回。
定義完成后,接下來,我們就可以直接在 MyAuthenticationProvider 中進(jìn)行調(diào)用了:
public class MyAuthenticationProvider extends DaoAuthenticationProvider { @Override protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { if (!((MyWebAuthenticationDetails) authentication.getDetails()).isPassed()) { throw new AuthenticationServiceException("驗證碼錯誤"); } super.additionalAuthenticationChecks(userDetails, authentication); } }
直接從 authentication 中獲取到 details 并調(diào)用 isPassed 方法,有問題就拋出異常即可。
最后的問題就是如何用自定義的 MyWebAuthenticationDetailsSource 代替系統(tǒng)默認(rèn)的 WebAuthenticationDetailsSource,很簡單,我們只需要在 SecurityConfig 中稍作定義即可:
@Autowired MyWebAuthenticationDetailsSource myWebAuthenticationDetailsSource; @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() ... .and() .formLogin() .authenticationDetailsSource(myWebAuthenticationDetailsSource) ... }
將 MyWebAuthenticationDetailsSource 注入到 SecurityConfig 中,并在 formLogin 中配置 authenticationDetailsSource 即可成功使用我們自定義的 WebAuthenticationDetails。
這樣自定義完成后,WebAuthenticationDetails 中原有的功能依然保留,也就是我們還可以利用老辦法繼續(xù)獲取用戶 IP 以及 sessionId 等信息,如下:
@Service public class HelloService { public void hello() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); MyWebAuthenticationDetails details = (MyWebAuthenticationDetails) authentication.getDetails(); System.out.println(details); } }
這里類型強(qiáng)轉(zhuǎn)的時候,轉(zhuǎn)為 MyWebAuthenticationDetails 即可。
到此,相信大家對“如何用SpringSecurity查看登錄”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。