您好,登錄后才能下訂單哦!
本篇內容主要講解“如何用SpringSecurity查看登錄”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何用SpringSecurity查看登錄”吧!
Authentication 這個接口前面和大家聊過多次,今天還要再來聊一聊。
Authentication 接口用來保存我們的登錄用戶信息,實際上,它是對主體(java.security.Principal)做了進一步的封裝。
我們來看下 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; }
接口的解釋如下:
鴻蒙官方戰略合作共建——HarmonyOS技術社區
getAuthorities 方法用來獲取用戶的權限。
getCredentials 方法用來獲取用戶憑證,一般來說就是密碼。
getDetails 方法用來獲取用戶攜帶的詳細信息,可能是當前請求之類的東西。
getPrincipal 方法用來獲取當前用戶,可能是一個用戶名,也可能是一個用戶對象。
isAuthenticated 當前用戶是否認證成功。
這里有一個比較好玩的方法,叫做 getDetails。關于這個方法,源碼的解釋如下:
Stores additional details about the authentication request. These might be an IP address, certificate serial number etc.
從這段解釋中,我們可以看出,該方法實際上就是用來存儲有關身份認證的其他信息的,例如 IP 地址、證書信息等等。
實際上,在默認情況下,這里存儲的就是用戶登錄的 IP 地址和 sessionId。我們從源碼角度來看下。
松哥的 SpringSecurity 系列已經寫到第 12 篇了,看了前面的文章,相信大家已經明白用戶登錄必經的一個過濾器就是 UsernamePasswordAuthenticationFilter,在該類的 attemptAuthentication 方法中,對請求參數做提取,在 attemptAuthentication 方法中,會調用到一個方法,就是 setDetails。
我們一起來看下 setDetails 方法:
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) { authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); }
UsernamePasswordAuthenticationToken 是 Authentication 的具體實現,所以這里實際上就是在設置 details,至于 details 的值,則是通過 authenticationDetailsSource 來構建的,我們來看下:
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; } //省略其他方法 }
默認通過 WebAuthenticationDetailsSource 來構建 WebAuthenticationDetails,并將結果設置到 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 中調用該方法,當訪問接口時,可以看到如下日志:
WebAuthenticationDetails@fffc7f0c: RemoteIpAddress: 127.0.0.1; SessionId: 303C7F254DF8B86667A2B20AA0667160
可以看到,用戶的 IP 地址和 SessionId 都給出來了。這兩個屬性在 WebAuthenticationDetails 中都有對應的 get 方法,也可以單獨獲取屬性值。
當然,WebAuthenticationDetails 也可以自己定制,因為默認它只提供了 IP 和 sessionid 兩個信息,如果我們想保存關于 Http 請求的更多信息,就可以通過自定義 WebAuthenticationDetails 來實現。
如果我們要定制 WebAuthenticationDetails,還要連同 WebAuthenticationDetailsSource 一起重新定義。
結合上篇文章的驗證碼登錄,我跟大家演示一個自定義 WebAuthenticationDetails 的例子。
上篇文章我們是在 MyAuthenticationProvider 類中進行驗證碼判斷的,回顧一下上篇文章的代碼:
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,由于它的構造方法中,剛好就提供了 HttpServletRequest 對象,所以我們可以直接利用該對象進行驗證碼判斷,并將判斷結果交給 isPassed 變量保存。如果我們想擴展屬性,只需要在 MyWebAuthenticationDetails 中再去定義更多屬性,然后從 HttpServletRequest 中提取出來設置給對應的屬性即可,這樣,在登錄成功后就可以隨時隨地獲取這些屬性了。
最后在 MyWebAuthenticationDetailsSource 中構造 MyWebAuthenticationDetails 并返回。
定義完成后,接下來,我們就可以直接在 MyAuthenticationProvider 中進行調用了:
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 并調用 isPassed 方法,有問題就拋出異常即可。
最后的問題就是如何用自定義的 MyWebAuthenticationDetailsSource 代替系統默認的 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 中原有的功能依然保留,也就是我們還可以利用老辦法繼續獲取用戶 IP 以及 sessionId 等信息,如下:
@Service public class HelloService { public void hello() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); MyWebAuthenticationDetails details = (MyWebAuthenticationDetails) authentication.getDetails(); System.out.println(details); } }
這里類型強轉的時候,轉為 MyWebAuthenticationDetails 即可。
到此,相信大家對“如何用SpringSecurity查看登錄”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。