1. 程式人生 > >Spring Security 實現身份認證

Spring Security 實現身份認證

   Spring Security可以執行在不同的身份認證環境中,當我們推薦使用者使用Spring Security進行身份認證但並不推薦整合到容器管理的身份認證中時,但當你整合到自己的身份認證系統時,它依然是支援的。

    1. Spring Security中的身份認證是什麼?

    現在讓我們考慮一下每個人都熟悉的標準身份認證場景:

    (1)使用者打算使用使用者名稱和密碼登陸系統

    (2)系統驗證使用者名稱和密碼合法

    (3)得到使用者資訊的上下文(角色等資訊)

    (4)為使用者建立一個安全上下文

    (5)使用者接下來可能執行一些許可權訪問機制下的受保護的操作,檢查與當前安全上下文有關的必須的許可權

    上面前三步是身份認證的過程,接下來看看身份認證的詳細過程:

    (1)使用者名稱和密碼獲得之後組合成 UsernamePasswordAuthenticationToken 的例項(前文討論過的Authentication介面的例項)

    (2)將該令牌傳遞給 AuthenticationManager 例項進行驗證

    (3)驗證成功後,AuthenticationManager 會返回填充好的 Authentication 例項

    (4)通過呼叫 SecurityContextHolder.getContext().setAuthentication(...)

 建立安全上下文的例項,傳遞到返回的身份認證物件上

    下面是進行身份認證的程式碼片段:

import org.springframework.security.authentication.*;
import org.springframework.security.core.*;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

public class AuthenticationExample {

private static AuthenticationManager am = new SampleAuthenticationManager();

public static void main(String[] args) throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
while(true) {
System.out.println("Please enter your username:");
String name = in.readLine();
System.out.println("Please enter your password:");
String password = in.readLine();
try {
Authentication request = new UsernamePasswordAuthenticationToken(name, password);
Authentication result = am.authenticate(request);
SecurityContextHolder.getContext().setAuthentication(result);
break;
} catch(AuthenticationException e) {
System.out.println("Authentication failed: " + e.getMessage());
}
}
System.out.println("Successfully authenticated. Security context contains: " +
SecurityContextHolder.getContext().getAuthentication());
}
}

class SampleAuthenticationManager implements AuthenticationManager {

static final List<GrantedAuthority> AUTHORITIES = new ArrayList<GrantedAuthority>();

static {
AUTHORITIES.add(new SimpleGrantedAuthority("ROLE_USER"));
}

public Authentication authenticate(Authentication auth) throws AuthenticationException {
if (auth.getName().equals(auth.getCredentials())) {
return new UsernamePasswordAuthenticationToken(auth.getName(),
auth.getCredentials(), AUTHORITIES);
}
throw new BadCredentialsException("Bad Credentials");
}

}

   我們寫了一個小程式,要求使用者輸入使用者名稱和密碼並執行上述序列。我們實現的 AuthenticationManager 會驗證使用者名稱和密碼是否一致,它分配了一個角色給每個使用者。上面的輸出類似於這樣:

Please enter your username:     

favboy

Please enter your password:

favccxx

Authentication failed: Bad Credentials

Please enter your username:

favboy

Please enter your password:

favboy

Successfully authenticated. Security context contains: \

 org.springframew[email protected]441d0230: \

 Principal: bob; Password: [PROTECTED]; \

 Authenticated: true; Details: null; \

 Granted Authorities: ROLE_USER




    注意,你通常不需要寫任何程式碼。這個過程通常發生在內部,如web身份認證過濾器。上面的程式碼僅僅是告訴我們在Spring Security中使用身份認證是如此簡單的事情。當 SecurityContextHolder 包含一個填充的 Authentication 物件時使用者身份就完成了。

    2. 直接設定 SecurityContextHolder的內容

    實際上,Spring Security並不關心如何將 Authentication物件放到SecurityContextHolder中。唯一的關鍵就是 SecurityContextHolder需要在使用者操作認證的 AbstractSecurityInterceptor 之前已經有了Authentication物件。

    對於那些不是Spring Security的系統,你可以自己寫過濾器或MVC控制器與身份認證系統進行整合。比如,你可能使用容器管理的身份認證系統從ThreadLocal或JNDI中得到使用者。也可能你在一個擁有遺留的身份認證系統的公司工作,這是一個企業的“標準”,對此你是無能為力的。在這種情形下,使用Spring Security提供身份認證是非常容易的,你只需要寫一個過濾器讀取第三方的使用者資訊,然後構建一個Spring Security特定的 Authentication物件,並把它放到AuthenticationContextHolder中即可。在這種情況下,你需要考慮自帶的身份認證的基礎資訊。比如,你需要在響應到客戶端之前,先建立一個HTTP session會話在請求之間快取上下文。

    3 在Web應用中使用身份認證

    接下來,我們探究一下Web應用不配置web.xml安全策略的情況下如何使用Spring Security進行身份認證,如何建立使用者身份認證和安全上下文?

    下面是web應用身份認證的流程:

    (1)訪問某應用的首頁,點選某個連結。

    (2)傳送一個請求到伺服器,伺服器判斷使用者是否正在訪問受保護的資源。

    (3)由於使用者之前並未進行身份認證,伺服器傳送一個響應(該響應可能是HTTP響應程式碼,也可能直接跳轉到某web頁面)告訴使用者必須進行身份認證。

    (4)身份認證機制決定了瀏覽器是跳轉到特定的web頁面讓使用者填寫form表單,或者瀏覽器以某種方式(基本的身份認證對話方塊、cookie或X.509證書)檢索使用者身份。

    (5)瀏覽器傳送響應(包含表單資訊的HTTP POST請求或是包含使用者身份認證詳細資訊的HTTP表頭)回伺服器。

    (6)接下來,伺服器會決定之前的憑證是否有效。如果有效的話,會進行下一步。否則的話,瀏覽器通常會詢問是否需要重試。

    (7)原始的請求會導致身份認證流程重新進行,重新判斷使用者有足夠的許可權訪問受保護的資源,如果使用者有許可權的話,請求就是成功的。否則的話,會返回HTTP錯誤碼403,表示使用者沒有許可權操作。

    Spring Security有具體的類負責上面的步驟,主要的類有 ExceptionTranslationFilter , AuthenticationEntryPoint 和呼叫AuenticationManager 的“身份認證機制”。

    3.1 ExceptionTranslationFilter

    顧名思義,ExceptionTranslationFilter是處理Spring Security中異常的過濾器,這些異常都是由提供身份認證服務的 AbstractSecurityInterceptor 丟擲。

    3.2 AuthenticationEntryPoint

    上面步驟3的操作中是 AuenticationEntryPoint 的職責,你能想象每個web應用都有預設的身份認證測試,每個主要的身份認證系統都有 AuthenticationEntryPoint 實現,通常執行步驟3中描述的行動之一。

    3.3 身份認證機制

    一旦你的瀏覽器提交了驗證證書(HTTP表單 POST或 HTTP頭),這需要伺服器上的一些東西儲存這些許可權資訊。但是現在進入上面的第6步,在Spring Security中我們有一個特定的名稱,為了手機驗證資訊的操作。從一個使用者代理中(通常是瀏覽器),引用它作為一個“驗證機制”。例如基於表單的登陸或BASIC驗證。一旦從使用者代理出收集到驗證細節, Authentication請求物件就會建立,然後提交給AuthenticationManager。

    身份認證機制收到填充好的 Authentication 物件之後,它會認為請求合法,把 Authentication放到SecurityContextHolder中,然後重試原始的請求(第7步)。如另一方面, AuthenticationManager拒絕了請求,身份認證機制會讓使用者代理重試(第2步)。

    3.4 在請求間儲存 SecurityContext

    根據應用型別,需要一個策略在使用者操作之間儲存security上下文。在典型的web應用中,一次使用者登陸日誌隨後就由它的session id所確定,伺服器為保持session會話會快取主體資訊。在Spring Security中,在請求間儲存SecurityContext的職責落在了 SecurityContextPersistenceFilter上,預設情況下,SecurityContextPersistenceFilter會在HTTP請求中將上下文儲存在HttpSession屬性上。每次請求的上下文都會儲存在 SecurityContextHolder上,而且,最重要的是,當請求完成時它會清除 SecurityContextHolder。為了安全方面考慮,使用者不應該直接操作 HttpSession,這裡有簡單的方法實現-使用 SecurityContextHolder代替。

    很多其他型別的應用(比如一個無狀態的REST Web服務)不會使用HTTP會話,會在每次請求時重新驗證。然而,將 SecurityContextPersistenceFilter包含了請求鏈中仍然是非常重要的,這樣就會確保在每次請求後 SecurityContextHolder會被清空。




    注意,你通常不需要寫任何程式碼。這個過程通常發生在內部,如web身份認證過濾器。上面的程式碼僅僅是告訴我們在Spring Security中使用身份認證是如此簡單的事情。當 SecurityContextHolder 包含一個填充的 Authentication 物件時使用者身份就完成了。

    2. 直接設定 SecurityContextHolder的內容

    實際上,Spring Security並不關心如何將 Authentication物件放到SecurityContextHolder中。唯一的關鍵就是 SecurityContextHolder需要在使用者操作認證的 AbstractSecurityInterceptor 之前已經有了Authentication物件。

    對於那些不是Spring Security的系統,你可以自己寫過濾器或MVC控制器與身份認證系統進行整合。比如,你可能使用容器管理的身份認證系統從ThreadLocal或JNDI中得到使用者。也可能你在一個擁有遺留的身份認證系統的公司工作,這是一個企業的“標準”,對此你是無能為力的。在這種情形下,使用Spring Security提供身份認證是非常容易的,你只需要寫一個過濾器讀取第三方的使用者資訊,然後構建一個Spring Security特定的 Authentication物件,並把它放到AuthenticationContextHolder中即可。在這種情況下,你需要考慮自帶的身份認證的基礎資訊。比如,你需要在響應到客戶端之前,先建立一個HTTP session會話在請求之間快取上下文。

    3 在Web應用中使用身份認證

    接下來,我們探究一下Web應用不配置web.xml安全策略的情況下如何使用Spring Security進行身份認證,如何建立使用者身份認證和安全上下文?

    下面是web應用身份認證的流程:

    (1)訪問某應用的首頁,點選某個連結。

    (2)傳送一個請求到伺服器,伺服器判斷使用者是否正在訪問受保護的資源。

    (3)由於使用者之前並未進行身份認證,伺服器傳送一個響應(該響應可能是HTTP響應程式碼,也可能直接跳轉到某web頁面)告訴使用者必須進行身份認證。

    (4)身份認證機制決定了瀏覽器是跳轉到特定的web頁面讓使用者填寫form表單,或者瀏覽器以某種方式(基本的身份認證對話方塊、cookie或X.509證書)檢索使用者身份。

    (5)瀏覽器傳送響應(包含表單資訊的HTTP POST請求或是包含使用者身份認證詳細資訊的HTTP表頭)回伺服器。

    (6)接下來,伺服器會決定之前的憑證是否有效。如果有效的話,會進行下一步。否則的話,瀏覽器通常會詢問是否需要重試。

    (7)原始的請求會導致身份認證流程重新進行,重新判斷使用者有足夠的許可權訪問受保護的資源,如果使用者有許可權的話,請求就是成功的。否則的話,會返回HTTP錯誤碼403,表示使用者沒有許可權操作。

    Spring Security有具體的類負責上面的步驟,主要的類有 ExceptionTranslationFilter , AuthenticationEntryPoint 和呼叫AuenticationManager 的“身份認證機制”。

    3.1 ExceptionTranslationFilter

    顧名思義,ExceptionTranslationFilter是處理Spring Security中異常的過濾器,這些異常都是由提供身份認證服務的 AbstractSecurityInterceptor 丟擲。

    3.2 AuthenticationEntryPoint

    上面步驟3的操作中是 AuenticationEntryPoint 的職責,你能想象每個web應用都有預設的身份認證測試,每個主要的身份認證系統都有 AuthenticationEntryPoint 實現,通常執行步驟3中描述的行動之一。

    3.3 身份認證機制

    一旦你的瀏覽器提交了驗證證書(HTTP表單 POST或 HTTP頭),這需要伺服器上的一些東西儲存這些許可權資訊。但是現在進入上面的第6步,在Spring Security中我們有一個特定的名稱,為了手機驗證資訊的操作。從一個使用者代理中(通常是瀏覽器),引用它作為一個“驗證機制”。例如基於表單的登陸或BASIC驗證。一旦從使用者代理出收集到驗證細節, Authentication請求物件就會建立,然後提交給AuthenticationManager。

    身份認證機制收到填充好的 Authentication 物件之後,它會認為請求合法,把 Authentication放到SecurityContextHolder中,然後重試原始的請求(第7步)。如另一方面, AuthenticationManager拒絕了請求,身份認證機制會讓使用者代理重試(第2步)。

    3.4 在請求間儲存 SecurityContext

    根據應用型別,需要一個策略在使用者操作之間儲存security上下文。在典型的web應用中,一次使用者登陸日誌隨後就由它的session id所確定,伺服器為保持session會話會快取主體資訊。在Spring Security中,在請求間儲存SecurityContext的職責落在了 SecurityContextPersistenceFilter上,預設情況下,SecurityContextPersistenceFilter會在HTTP請求中將上下文儲存在HttpSession屬性上。每次請求的上下文都會儲存在 SecurityContextHolder上,而且,最重要的是,當請求完成時它會清除 SecurityContextHolder。為了安全方面考慮,使用者不應該直接操作 HttpSession,這裡有簡單的方法實現-使用 SecurityContextHolder代替。

    很多其他型別的應用(比如一個無狀態的REST Web服務)不會使用HTTP會話,會在每次請求時重新驗證。然而,將 SecurityContextPersistenceFilter包含了請求鏈中仍然是非常重要的,這樣就會確保在每次請求後 SecurityContextHolder會被清空。

相關推薦

Spring Security 實現身份認證

   Spring Security可以執行在不同的身份認證環境中,當我們推薦使用者使用Spring Security進行身份認證但並不推薦整合到容器管理的身份認證中時,但當你整合到自己的身份認證系統時,它依然是支援的。     1. Spring Security中

SpringMVC+Spring Security實現登入認證的簡單功能

一、依賴pom.xml 這裡僅僅列出security需要的依賴,其他依賴見前面Spring目錄下文章。 <!-- Spring Security -->      <dependency>          <groupId>org

spring實戰-Spring-security實現使用者許可權認證登入

第八篇:Spring-security實現使用者許可權認證登入 spring-security原本是Acegi Security元件,該元件是一個強大的安全框架,但是使用方式很繁瑣,要配置幾百行XML。整合進Spring後,就可以通過xml或者JavaConfig的方式,很容易的就實現了系統

spring security實現登入驗證以及根據使用者身份跳轉不同頁面

想關依賴,採用session加redis儲存使用者資訊 <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security

Spring Cloud 安全:整合OAuth2實現身份認證和單點登入

1、概述 Spring Cloud 的安全模組可以為Spring Boot應用提供基於令牌的安全特性。具體講就是支援OAuth2協議來實現單點登入(SSO),可以很方便地在資源服務之間傳遞身份令牌,以及使用嵌入式的ZUUL代理來配置下游服務的認證。 在這篇文

spring security oauth2 jwt 認證和資源分離的配置文件(java類配置版)

boot cond lan 資源分離 測試 sql adapter 依賴 註入 最近再學習spring security oauth2。下載了官方的例子sparklr2和tonr2進行學習。但是例子裏包含的東西太多,不知道最簡單最主要的配置有哪些。所以決定自己嘗試搭建簡單版

redis jwt spring boot spring security 實現api token 驗證

BE output date art parent byte[] web rmi time 文章地址:http://www.haha174.top/article/details/258083 項目源碼:https://github.com/haha174/jwt-toke

Spring Boot中使用Spring Security實現權限控制

unicode then add sta spa 攔截器 nco throw views Spring Boot框架我們前面已經介紹了很多了,相信看了前面的博客的小夥伴對Spring Boot應該有一個大致的了解了吧,如果有小夥伴對Spring Boot尚不熟悉

Spring security實現國際化問題

ryu rep util ets prope name format 自帶 method 這兩天Spring用戶登錄國際化這個問題困擾我好久啊,於昨天晚上終於把它幹掉了。 場景就是我們公司的產品-incopat,需要支持中英文,用戶登錄這塊用的spring自帶的securi

spring-security-oauth2(三) 認證流程原始碼分析

認證流程原始碼分析 之前的程式碼中,我們自定義了登陸路徑,自定義成功和失敗處理器以及自定義的使用者登陸資訊校驗,下面我們通過簡單的原始碼分析,來把這些串聯起來 認證流程處理說明 認證結果如何在多個請求之間共享 獲取認證使用者資訊 認證處理流程說明 spring-

Spring Security 實現 antMatchers 配置路徑的動態獲取

1. 為什麼要實現動態的獲取 antMatchers 配置的資料           這兩天由於公司專案的需求,對 spring security 的應用過程中需要實現動態的獲取 antMatch

Spring security實現程式碼登入

首先,現階段網上的spring security配置資料中都涉及登入頁面的的登入。幾乎找不到根據使用者名稱密碼直接登入的方式。現將該方式記錄下來。 我碰到的問題:這是一個很常見的業務需求,使用者訪問系統傳送請求時帶了使用者資訊引數,不需要將頁面跳轉到登入頁面進行登入,直接通

spring-boot整合spring-security實現簡單登入(ajax登入實現)

平常再做一些專案時,有些專案並不需要複雜的登入許可權驗證 只需要簡單登入許可權驗證(保證安全可靠的前提下),找來找去只有spring-security最適合不過了,在spring-boot下配置簡單 便捷 快速 能滿足基本的登入許可權控制需求。 第一步:引入spring

利用spring-security實現登入

首先建立maven工程(war) pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:sc

spring boot中spring security實現單點登入,傳統模式(一)

單點登入是什麼? 一個系統中可能會引用別的很多系統。單點登入就是解決,一次登入,就可以訪問所有的系統。 每次瀏覽器向一個域名傳送http請求,會去查詢域名的cookie資訊拼接到http的header中傳送到伺服器。 cookie不能跨域。這個域是瀏覽器請求的域名,哪怕他們都是訪問一

spring-security 個性化使用者認證流程——自定義登入頁面(可配置)

1.定義自己的登入頁面我們需要根據自己的業務系統構建自己的登入頁面以及登入成功、失敗處理在spring security提供給我的登入頁面中,只有使用者名稱、密碼框,而自帶的登入成功頁面是空白頁面(可以重定向之前請求的路徑中),而登入失敗時也只是提示使用者被鎖定、過期等資訊。 在實際的開發中,則需要更

Spring系列學習之Spring Security OAuth身份驗證與授權

英文原文:https://spring.io/projects/spring-security-oauth 目錄 概述 特性 快速開始 學習 文件 概述 Spring Security OAuth使用標準的Spring和Spring Security程式設計模型和

Spring系列學習之Spring Security SAML身份驗證與授權

英文原文:http://projects.spring.io/spring-security-saml/ 目錄 Spring Security SAML 特性 快速開始 版本 資源 Spring Security SAML Spring Security Exte

Spring Security實現使用者名稱或者手機號登入

使用Spring Security來管理web專案的使用者許可權,是很多Java管理系統經常使用的方法。 然而,當前很多網站都支援使用手機號+密碼登入網站。畢竟,使用者名稱這個東西肯定沒有自己的手機號好記。 Spring Security許可權管理 Spr

Spring security實現許可權管理

1、配置檔案 1、POM.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schema