使用API??身份驗證的Spring Security

背景

盡管有許多博客文章詳細介紹了如何使用Spring Security,但是當問題域位于標準LDAP或數據庫身份驗證之外時,我仍然經常發現配置挑戰。 在本文中,我將介紹一些針對Spring Security的簡單自定義,使其能夠與基于REST的API調用一起使用。 具體來說,用例是您擁有一個API服務,該服務將返回包含SHA-256密碼哈希的用戶對象。

設定

運行此樣本的先決條件是Git和Maven,以及您選擇的IDE(已通過Eclipse和IntelliJ進行了測試)。

可以在以下位置找到源代碼: https : //github.com/dajevu/Spring3SecurityUsingAPI 。 拉下代碼后,執行以下步驟:

  1. 在終端窗口中,cd到位于源代碼所在根目錄下的Shared目錄。
  2. 發出命令mvn clean install。 這將構建Shared子項目,并將jar安裝到本地mvn存儲庫中。
  3. 在Eclipse或IntelliJ中,將項目導入為Maven項目。 在Eclipse中,這將導致創建3個項目:Shared,SpringWebApp和RestfulAPI。 在IntelliJ中,這將表示為子項目。 編譯過程完成后,不應有任何錯誤。
  4. 將目錄更改為RestfulAPI。 然后,發出命令mvn jetty:run以運行API webapp。 然后,您可以發出以下URL,該URL將帶回以JSON表示的User對象:http:// localhost:9090 / RestfulAPI / api / v1 / user / john
  5. 打開一個新的終端窗口,cd到位于項目根目錄下的SpringWebApp目錄。 發出命令mvn jetty:run。 這將啟動一個包含Spring Security的標準Spring Webapp。 您可以在以下位置訪問單個HTML頁面:http:// localhost:8080 / SpringWebApp /。 單擊“登錄”鏈接后,使用用戶名john和密碼doe登錄。 您應該被重定向到Hello Admin頁面。

    為了演示該解決方案,使用了三個Maven模塊,如下所示:

    • SpringWebApp 。 這是一個典型的Spring Webapp,僅提供一個JSP頁面。 頁面的內容將取決于用戶當前是否登錄。 首次訪問該頁面時,將顯示一個Login鏈接,該鏈接將其定向到內置的Spring Security登錄表單。 當他們嘗試登錄時, R ESTEasy客戶端用于調用API服務(如下所述),該服務返回一個JSON字符串,該字符串通過RESTEasy客戶端轉換為Java對象。 以下各節討論了如何配置Spring Security的詳細信息。
    • RestfulAPI 。 提供JSON請求的API服務。 它是使用RESTEasy(JAX-RS實現)配置的,下一節將對其進行詳細描述。
    • 共享的 。 它包含其他兩個項目之間共享的一些Java類。 具體來說,用戶對象DTO和RESTEasy代理定義(由于RESTEasy客戶端也可以使用它,因此已共享)。

    RestfulAPI解剖

    API Webapp是使用RESTEasy的Spring實現配置的。 RESTEasy文檔非常詳盡,因此我將不對其設置進行詳細說明。 定義了一個API調用(在Shared項目的UserProxy中),該調用返回靜態JSON字符串。 API的代理(或接口)定義如下:

    Resteasy API代理

    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Path(UserProxy.Urls.BASE_URL)
    public interface UserProxy {public interface Urls {public static final String BASE_URL = "/api/v1";public static final String USER = "/user/{username}";}@GET@Produces( { MediaType.APPLICATION_JSON })@Path(UserProxy.Urls.USER)public User getUserByUsername(@PathParam("username") String username);
    }

    對于那些熟悉JAX-RS的人來說,您將可以輕松地遵循此配置。 它定義了一個API URI,它將響應發送到/ api / v1 / user / {username}的URL路徑的請求,其中{username}被替換為實際的用戶名值。 該服務的實現僅返回一個靜態響應,如下所示:

    關于唯一復雜的事情是使用用戶密碼的SHA-256哈希。 很快我們將看到Spring Security如何解釋這一點。 訪問URL時,將返回以下JSON字符串:

    該Webapp的web.xml包含用于服務于RESTEasy請求的設置配置,因此,如果您好奇的話,請看一下。

    SpringWebApp解剖

    現在我們可以看一下Spring Security的配置。 項目的web.xml文件將其配置為Spring應用程序,并將文件applicationContext-security.xml指定為初始Spring配置文件。 讓我們仔細看一下這個文件,因為這是大多數魔術發生的地方:
    讓我們遍歷每個行號以描述其功能。 第3至5行指示Spring在com.acme目錄中查找Spring支持的類,并且將支持Spring批注。 第7行用于加載application.properties文件中指定的屬性(用于指定API主機)。 第9至11行為該應用程序啟用Spring Security。 通常,作為http的子元素,您將指定使用角色來保護哪些頁面,但是為了使本示例簡單起見,未對其進行配置。

    第13-17行是基于Spring Security的自定義開始的地方。 我們通過其bean ref定義了一個名為userDetailsS??rv的自定義身份驗證提供程序。 該bean通過自定義類com.acme.security.UserDetailsS??ervice實現(第19行)。 讓我們仔細看一下這個類:

    如您所見,此類實現了Spring接口org.springframework.security.core.userdetails.UserDetailsS??ervice。 這需要覆蓋方法loadUserByUsername。 此方法負責從身份驗證提供者/源中檢索用戶。 返回的用戶(或者,如果找不到匹配的用戶,則拋出UsernameNotFoundException-第28行)必須包含密碼屬性,以便Spring Security與表單中提供的內容進行比較。 如前所述,在這種情況下,密碼以SHA-256哈希值返回。

    在我們的API實現中,使用API??Helper類提取用戶查找,我們將在后面介紹。 然后,將返回的API數據填充到名為UserDetails的自定義類中。 這將使用相同的名稱實現Spring接口。 該接口需要getUsername()和getPassword()方法的具體實現。 Spring將在Security的下一個處理步驟中調用這些值,以將這些值與Web表單中記錄的值進行比較。

    Spring如何將SHA-256中返回的密碼與表單密碼值進行比較。 如果回頭看一下XML配置,它包含以下設置:
    注意passwordEncoder -該參考指向Spring類ShaPasswordEncoder。 此類將計算通過Web表單提供的密碼的SHA-256密碼,然后Spring會將計算出的值與我們通過API返回的值進行比較。

    讓我們通過看一下APIHelper類來解決這個問題:

    第8和9行的第一件事是注入API.host屬性。 您還記得,這是在application.properties文件中設置的。 這標識了要在其中發布API調用的主機(因為它在本地運行,所以指定了localhost)。 第17至20行使用RESTEasy客戶端機制之一發布JSON RESTful調用(RESTEasy也具有所謂的客戶端代理實現,它更易于使用/代碼更少,但沒有提供太多的低級控制)。 然后,通過第26行的Jackson方式,將來自API的結果響應從JSON轉換為User Java對象。然后將該Java對象返回給UserDetails服務。

    總結/總結

    如您所見,定制Spring Security以針對API調用(或實際上是任何外部服務)進行身份驗證所涉及的實際工作非常簡單。 只需要實現幾個類,但是嘗試第一次弄清楚這一點可能很棘手。 因此,之所以我包括完整的端到端示例。

    參考:來自Jeff's SOA Ruminations博客的JCG合作伙伴 Jeff Davis 使用API??身份驗證的Spring Security 。


    翻譯自: https://www.javacodegeeks.com/2012/10/spring-security-using-api-authentication.html

    本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
    如若轉載,請注明出處:http://www.pswp.cn/news/371168.shtml
    繁體地址,請注明出處:http://hk.pswp.cn/news/371168.shtml
    英文地址,請注明出處:http://en.pswp.cn/news/371168.shtml

    如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

    相關文章

    java nlpir_4-NLPIR漢語分詞系統-JAVA

    好吧,之前用的是舊版的,現在出了個新版的,優先選擇用新版的哈。從官網下載相應的開發包,然后主要需要找到這幾個東西添加到項目工程里面,1.Data文件夾 2.NLPIR_JNI.DLL 3.NLPIR.jar 4.nlpir.properties添加完那些東西后…

    淺析C語言中assert的用法(轉)

    原文地址&#xff1a;http://www.jb51.net/article/39685.htm 以下是對C語言中assert的使用方法進行了介紹&#xff0c;需要的朋友可以參考下。 assert宏的原型定義在<assert.h>中&#xff0c;其作用是如果它的條件返回錯誤&#xff0c;則終止程序執行&#xff0c;原型定…

    hihocoder offer收割編程練習賽12 D 尋找最大值

    思路&#xff1a; 可能數據太水了&#xff0c;隨便亂搞就過了。 實現&#xff1a; 1 #include <iostream>2 #include <cstdio>3 #include <algorithm>4 using namespace std;5 typedef long long ll;6 7 int a[100005], n;8 9 int main() 10 { 11 int t;…

    vue error:The template root requires exactly one element.

    error:[vue/valid-template-root] The template root requires exactly one element. 原因&#xff1a; 因為vue的模版中只有能一個根節點&#xff0c;所以在<template>中插入第二個元素就會報錯 解決方案&#xff1a; 將<template>中的元素先用一個<div>…

    測試驅動陷阱,第2部分

    單元測試中單元的故事 在本文的上半部分 &#xff0c;您可能會看到一些不好但很流行的測試示例。 但是我不是一個專業評論家&#xff08;也被稱為“巨魔”或“仇恨者”&#xff09;&#xff0c;沒有任何建設性的話就抱怨。 多年的TDD教給我的不僅僅是事情會變得多么糟糕。 有許…

    java 代碼 設置環境變量_Java 配置環境變量教程

    【聲明】歡迎轉載&#xff0c;但請保留文章原始出處→_→【正文】1、安裝JDK開發環境開始安裝JDK&#xff1a;修改安裝目錄如下&#xff1a;確定之后&#xff0c;單擊“下一步”。注&#xff1a;當提示安裝JRE時&#xff0c;可以選擇不要安裝。2、配置環境變量&#xff1a;對于…

    組合數據類型練習,英文詞頻統計實例上(2017.9.22)

    字典實例&#xff1a;建立學生學號成績字典&#xff0c;做增刪改查遍歷操作。 sno[33號,34號,35號,36號] grade[100,90,80,120] d{33號:100,34號:90,35號:80,36號:120} print(d) print(每個學號對應分數:,d.items()) print(彈出35號的分數:,d.pop(35號)) print(獲取學號:,d.key…

    java 代碼中設置 臨時 環境變量

    System.setProperty("hadoop.home.dir", "D:\\software\\software_install\\dev_install\\hadoop-2.4.1"); 轉載于:https://www.cnblogs.com/zychengzhiit1/p/6662376.html

    什么是快速開發框架

    什么是快速開發框架 前言 做為一個程序員&#xff0c;在開發的過程中會發現&#xff0c;有框架同無框架&#xff0c;做起事來是完全不同的概念&#xff0c;關系到開發的效率、程序的健壯、性能、團隊協作、后續功能維護、擴展......等方方面面的事情。很多朋友在學習搭建自己…

    java中的math.abs_Java.math.BigDecimal.abs()方法

    全屏Java.math.BigDecimal.abs()方法java.math.BigDecimal.abs()返回一個BigDecimal&#xff0c;其值是此BigDecimal的絕對值&#xff0c;其標度是this.scale()。聲明以下是java.math.BigDecimal.abs()方法的聲明public BigDecimal abs()參數NA返回值此方法返回的名為value&…

    我需要多少內存

    什么是保留堆&#xff1f; 我需要多少內存&#xff1f; 在構建解決方案&#xff0c;創建數據結構或選擇算法時&#xff0c;您可能會問自己&#xff08;或其他人&#xff09;這個問題。 如果此圖包含1,000,000條邊并且我使用HashMap進行存儲&#xff0c;此圖是否適合我的3G堆&am…

    C語言程序設計預報作業

    1閱讀鄒欣老師的博客--師生關系,針對文中的幾種師生關系談談你的看法&#xff0c;你期望的師生關系是什么樣的&#xff1f; 答&#xff1a;我認為文中的師生關系都存在一些缺陷&#xff0c;第一種師生關系是建立在病態關系上的&#xff0c;學生不是植物自然有自己的思想。所以我…

    淺談23種設計模式

    淺談23種設計模式 類之間的關聯關系&#xff1a;在使用Java、C#和C等編程語言實現關聯關系時&#xff0c;通常將一個類作為另一個類的屬性。   (1)雙向關聯&#xff0c;兩個類互相為各自的屬性&#xff0c;比如顧客類Customer和商品類Product&#xff0c;顧客擁有商品&#x…

    網頁布局基礎

    1、盒子模型的第一層到第五層&#xff1a; border、padding content、background-image、background-color、margin 2、清除浮動。對受到浮動影響的標簽作以下操作&#xff1a; 1、clear: both; 2、clear: right; clear: left; 3、設置寬度width: 100%(或者固定寬度) overflow…

    mysql與串口通信_虛擬機串口與主機串口通信·小程序(下)

    上次說到的&#xff0c;不能做到實時通信。那么開兩個進程就可以了&#xff0c;一個用來監聽是否有消息傳來&#xff0c;一個用來等待用戶輸入。那么&#xff0c;先來復習一下進程的相關概念。進程結構linux中進程包含PCB(進程控制塊)、程序以及程序所操縱的數據結構集&#xf…

    淺談我所見的CSS命名風格

    在兩年工作中&#xff0c;總結一下我所見的css命名風格。 1.單一class命名 .header {width: 500px; } .item {text-indent: 20%; } 優點&#xff1a;簡單&#xff0c;渲染效率高。 缺點&#xff1a;零散&#xff0c;沒有模塊化。 2. 后代選擇器class命名 .header .item a {font…

    Java規范請求中的數字

    你們都了解Java社區流程 &#xff08;JCP&#xff09;&#xff0c;不是嗎&#xff1f; JCP是為Java技術開發標準技術規范的機制。 任何人都可以注冊該站點并參與對Java規范請求&#xff08;JSR&#xff09;的審查和提供反饋&#xff0c;并且任何人都可以注冊成為JCP成員&#x…

    ORACLE MOS 翻譯

    http://blog.csdn.net/msdnchina/article/details/53174196轉載于:https://www.cnblogs.com/zengkefu/p/6665950.html

    自從我這樣擼代碼以后,公司網頁的瀏覽量提高了107%!

    歡迎大家前往騰訊云 社區&#xff0c;獲取更多騰訊海量技術實踐干貨哦~ 本文由騰訊IVWEB團隊發表于云 社區專欄 作者&#xff1a;yangchunwen HTTP協議是前端性能乃至安全中一個非常重要的話題&#xff0c;最近在看《web性能權威指南(High Performance Browser Networking)》&a…

    python數列分段_按范圍分段的Python數組

    首先&#xff0c;定義你的“極”數第二&#xff0c;根據這些“極”數生成間隔第三&#xff0c;定義盡可能多的列表。在然后&#xff0c;對于每個間隔&#xff0c;掃描列表并在相關列表中添加屬于該間隔的項代碼&#xff1a;source [1, 4, 7, 9, 2, 10, 5, 8]poles (0,3,6,25)…