保護web應用的安全
原文:Securing a Web Application
譯者:lexburner校對:zaixiandemiao
本指南將引導你使用Spring Security來保護Web應用的安全。
你將要構建什麼
你將構建一個Spring MVC應用程序,該應用程序使用一些固定的用戶,支持表單登錄的形式來保護頁面。
你需要什麼
- 約15分鐘
- 一個你喜歡的文本編輯器或IDE
- JDK≥1.8
- Gradle 2.3+ or Maven 3.0+
- 你也可以將代碼直接導入你的IDE:
- Spring Tool Suite (STS)
- IntelliJ IDEA
如何完成這篇指南
像大多數的Spring指南 Getting Started guides,你可以從頭開始,完成每一步,也可以跳過已經熟悉的基本設置。 無論哪種方式,你都會得到起作用的代碼。
如果從基礎開始, 移步 使用Gradle構建.
如果你想跳過基礎部分, 執行以下操作:
- 下載 並解壓本倉庫的源碼, 或者使用 Git:
git clone https://github.com/spring-guides/gs-securing-web.git
- 進入
gs-securing-web/initial
- 前往 安裝 Spring Security.
當你完成後, 你可以和此處的代碼進行對比 gs-securing-web/complete
.
<h2 id="scratch">使用Gradle構建</h2>
首先你得安裝基礎的構建腳本. 可以使用任意你喜歡的構建系統去構建Spring應用, 而使用 Gradle 和 Maven構建需要的代碼在本文提供: Gradle 和 Maven . 如果你對兩者都不熟悉,可以先參考Building Java Projects with Gradle 或者 Building Java Projects with Maven.
創建目錄結構
在你選擇的項目目錄中,創建以下子目錄結構;例如, 在Linux/Unix系統中使用如下命令: mkdir -p src/main/java/hello
└── srcn └── mainn └── javan └── hellon
創建一個Gradle文件
如下是一個 Gradle初始化文件:
build.gradle
buildscript {n repositories {n mavenCentral()n }n dependencies {n classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.7.RELEASE")n }n}nnapply plugin: javanapply plugin: eclipsenapply plugin: ideanapply plugin: org.springframework.bootnnjar {n baseName = gs-securing-webn version = 0.1.0n}nnrepositories {n mavenCentral()n}nnsourceCompatibility = 1.8ntargetCompatibility = 1.8nndependencies {n compile("org.springframework.boot:spring-boot-starter-thymeleaf")n testCompile("junit:junit")n testCompile("org.springframework.boot:spring-boot-starter-test")n testCompile("org.springframework.security:spring-security-test")nn}n
Spring Boot gradle 插件 提供了很多便捷的特性:
- 它收集類路徑上的所有jar包,並構建一個可運行的jar包,這樣可以更方便地執行和發布服務。
- 它尋找
public static void main()
方法並標記為一個可執行的類. - 它提供了一個內置的依賴解析器,將應用與Spring Boot依賴的版本號進行匹配。你可以修改成任意的版本,但它將默認為Boot所選擇的一組版本。
使用Maven構建
首先,你需要設置一個基本的構建腳本。當使用Spring構建應用程序時,你可以使用任何你喜歡的構建系統,而使用 Maven 構建的代碼如下所示。如果你不熟悉Maven,請參考使用Maven構建Java項目。
創建目錄結構
在你選擇的項目目錄中,創建以下子目錄結構;例如, 在Linux/Unix系統中使用如下命令: mkdir -p src/main/java/hello
└── srcn └── mainn └── javan └── hellon
pom.xml
<?xml version="1.0" encoding="UTF-8"?>n<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"n xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">n <modelVersion>4.0.0</modelVersion>nn <groupId>org.springframework</groupId>n <artifactId>gs-securing-web</artifactId>n <version>0.1.0</version>nn <parent>n <groupId>org.springframework.boot</groupId>n <artifactId>spring-boot-starter-parent</artifactId>n <version>1.5.7.RELEASE</version>n </parent>nn <dependencies>n <dependency>n <groupId>org.springframework.boot</groupId>n <artifactId>spring-boot-starter-thymeleaf</artifactId>n </dependency>n <dependency>n <groupId>org.springframework.boot</groupId>n <artifactId>spring-boot-starter-test</artifactId>n <scope>test</scope>n </dependency>n <dependency>n <groupId>org.springframework.security</groupId>n <artifactId>spring-security-test</artifactId>n <scope>test</scope>n </dependency>n </dependencies>nn <properties>n <java.version>1.8</java.version>n </properties>nn <build>n <plugins>n <plugin>n <groupId>org.springframework.boot</groupId>n <artifactId>spring-boot-maven-plugin</artifactId>n </plugin>n </plugins>n </build>nn <repositories>n <repository>n <id>spring-releases</id>n <name>Spring Releases</name>n <url>https://repo.spring.io/libs-release</url>n </repository>n </repositories>n <pluginRepositories>n <pluginRepository>n <id>spring-releases</id>n <name>Spring Releases</name>n <url>https://repo.spring.io/libs-release</url>n </pluginRepository>n </pluginRepositories>n</project>n
Spring Boot Maven 插件 提供了很多便捷的特性:
- 它收集類路徑上的所有jar包,並構建一個可運行的jar包,這樣可以更方便地執行和發布服務。
- 它尋找
public static void main()
方法並標記為一個可執行的類. - 它提供了一個內置的依賴解析器,將應用與Spring Boot依賴的版本號進行匹配。你可以修改成任意的版本,但它將默認為Boot所選擇的一組版本。
使用你的IDE構建
- 閱讀如何導入這篇指南進入你的IDE Spring Tool Suite.
- 閱讀如何使用 IntelliJ IDEA 來構建.
創建一個不受安全保護的web應用
在保護Web應用程序安全之前,您需要安裝Web應用程序。 本節將引導你創建一個非常簡單的Web應用程序。 然後在下一節中使用Spring Security來保護它。
Web應用程序包括兩個簡單的視圖:主頁和「Hello World」頁面。 主頁定義在如下的Thymeleaf模板中:
src/main/resources/templates/home.html
<!DOCTYPE html>n<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">n <head>n <title>Spring Security Example</title>n </head>n <body>n <h1>Welcome!</h1>nn <p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>n </body>n</html>n
我們可以看到, 在這個簡單的視圖中包含了一個鏈接: 「/hello」. 鏈接到了如下的頁面,Thymeleaf模板如下:
src/main/resources/templates/hello.html
<!DOCTYPE html>n<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"n xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">n <head>n <title>Hello World!</title>n </head>n <body>n <h1>Hello world!</h1>n </body>n</html>n
Web應用程序基於Spring MVC。 因此,你需要配置Spring MVC並設置視圖控制器來暴露這些模板。 如下是一個典型的Spring MVC配置類。
src/main/java/hello/MvcConfig.java
package hello;nnimport org.springframework.context.annotation.Configuration;nimport org.springframework.web.servlet.config.annotation.ViewControllerRegistry;nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;nn@Configurationnpublic class MvcConfig extends WebMvcConfigurerAdapter {nn @Overriden public void addViewControllers(ViewControllerRegistry registry) {n registry.addViewController("/home").setViewName("home");n registry.addViewController("/").setViewName("home");n registry.addViewController("/hello").setViewName("hello");n registry.addViewController("/login").setViewName("login");n }nn}n
addViewControllers()
方法(覆蓋WebMvcConfigurerAdapter
中同名的方法)添加了四個視圖控制器。 兩個視圖控制器引用名稱為「home」的視圖(在home.html
中定義),另一個引用名為「hello」的視圖(在hello.html
中定義)。 第四個視圖控制器引用另一個名為「login」的視圖。 您將在下一部分中創建該視圖。
此時,您可以跳過來使應用程序可執行並運行應用程序,而無需登錄任何內容。
創建基本的簡單Web應用程序後,可以添加安全性。
安裝 Spring Security
假設你希望防止未經授權的用戶訪問「/ hello」。 此時,如果用戶點擊主頁上的鏈接,他們會看到問候語,請求被沒有被攔截。 你需要添加一個障礙,使得用戶在看到該頁面之前登錄。
您可以通過在應用程序中配置Spring Security來實現。 如果Spring Security在類路徑上,則Spring Boot會使用「Basic認證」來自動保護所有HTTP端點。 同時,你可以進一步自定義安全設置。 你需要做的第一件事是將Spring Security添加到類路徑中。
使用Gradle:
build.gradle
dependencies {n ...n compile("org.springframework.boot:spring-boot-starter-security")n ...n}n
使用maven,需要添加到 <dependencies>
節點中 :
pom.xml
<dependencies>n ...n <dependency>n <groupId>org.springframework.boot</groupId>n <artifactId>spring-boot-starter-security</artifactId>n </dependency>n ...n</dependencies>n
如下是安全配置,使得只有認證過的用戶才可以訪問到問候頁面:
src/main/java/hello/WebSecurityConfig.java
package hello;nnimport org.springframework.beans.factory.annotation.Autowired;nimport org.springframework.context.annotation.Configuration;nimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;nimport org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;nn@Configurationn@EnableWebSecuritynpublic class WebSecurityConfig extends WebSecurityConfigurerAdapter {n @Overriden protected void configure(HttpSecurity http) throws Exception {n httpn .authorizeRequests()n .antMatchers("/", "/home").permitAll()n .anyRequest().authenticated()n .and()n .formLogin()n .loginPage("/login")n .permitAll()n .and()n .logout()n .permitAll();n }nn @Autowiredn public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {n authn .inMemoryAuthentication()n .withUser("user").password("password").roles("USER");n }n}n
WebSecurityConfig
類使用了@EnableWebSecurity
註解 ,以啟用Spring Security的Web安全支持,並提供Spring MVC集成。它還擴展了WebSecurityConfigurerAdapter
,並覆蓋了一些方法來設置Web安全配置的一些細節。
configure(HttpSecurity)
方法定義了哪些URL路徑應該被保護,哪些不應該。具體來說,「/」和「/ home」路徑被配置為不需要任何身份驗證。所有其他路徑必須經過身份驗證。
當用戶成功登錄時,它們將被重定向到先前請求的需要身份認證的頁面。有一個由 loginPage()
指定的自定義「/登錄」頁面,每個人都可以查看它。
對於configureGlobal(AuthenticationManagerBuilder)
方法,它將單個用戶設置在內存中。該用戶的用戶名為「user」,密碼為「password」,角色為「USER」。
現在我們需要創建登錄頁面。前面我們已經配置了「login」的視圖控制器,因此現在只需要創建登錄頁面即可:
src/main/resources/templates/login.html
<!DOCTYPE html>n<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"n xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">n <head>n <title>Spring Security Example </title>n </head>n <body>n <div th:if="${param.error}">n Invalid username and password.n </div>n <div th:if="${param.logout}">n You have been logged out.n </div>n <form th:action="@{/login}" method="post">n <div><label> User Name : <input type="text" name="username"/> </label></div>n <div><label> Password: <input type="password" name="password"/> </label></div>n <div><input type="submit" value="Sign In"/></div>n </form>n </body>n</html>n
你可以看到,這個Thymeleaf模板只是提供一個表單來獲取用戶名和密碼,並將它們提交到「/ login」。 根據配置,Spring Security提供了一個攔截該請求並驗證用戶的過濾器。 如果用戶未通過認證,該頁面將重定向到「/ login?error」,並在頁面顯示相應的錯誤消息。 註銷成功後,我們的應用程序將發送到「/ login?logout」,我們的頁面顯示相應的登出成功消息。
最後,我們需要向用戶提供一個顯示當前用戶名和登出的方法。 更新hello.html
向當前用戶列印一句hello,並包含一個「註銷」表單,如下所示:
src/main/resources/templates/hello.html
<!DOCTYPE html>n<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"n xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">n <head>n <title>Hello World!</title>n </head>n <body>n <h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>n <form th:action="@{/logout}" method="post">n <input type="submit" value="Sign Out"/>n </form>n </body>n</html>n
我們使用Spring Security與HttpServletRequest#getRemoteUser()
的集成來顯示用戶名。 「登出」表單將POST請求提交到「/ logout」。 成功註銷後,會將用戶重定向到「/ login?logout」。
讓應用跑起來
雖然可以將此服務打包成傳統的Web應用程序或WAR 包以部署到外部的應用伺服器,但下面將演示一種更簡單的方法,創建一個獨立的應用程序。 所有內容都將包裝在一個可執行的JAR文件中,並使用Java的main()方法驅動。 這樣,你就可以使用Spring提供的內嵌Tomcat servlet容器,來運行HTTP服務,而不是部署到外部實例。
src/main/java/hello/Application.java
package hello;nnimport org.springframework.boot.SpringApplication;nimport org.springframework.boot.autoconfigure.SpringBootApplication;nn@SpringBootApplicationnpublic class Application {nn public static void main(String[] args) throws Throwable {n SpringApplication.run(Application.class, args);n }nn}n
@SpringBootApplication
是一個便捷的註解,它包含了如下的作用:
@Configuration
標記了該類為Spring應用上下文定義Bean的源頭.@EnableAutoConfiguration
告訴Spring Boot基於類路徑,其他類,多種設置添加Bean的定義.- 通常你需要為Spring MVC應用添加
@EnableWebMvc
註解 , 但springboot如果發現類路徑下存在spring-webmvc 的依賴,其會自動添加web的支持. 這便將應用標記為了一個web應用 並且激活了核心的配置如DispatcherServlet
. @ComponentScan
告訴Spring去掃描位於hello
包下的其他組件,配置和服務( components, configurations, and services), 同時讓它去尋找控制器(controllers).
main()
方法使用Spring Boot的 SpringApplication.run()
方法去運行應用. 發現沒有,我們沒有寫任何一行XML?也不存在 web.xml 文件. 這個web應用100%都是 Java 並且你不必配置任何基礎設施。
構建可執行的JAR包
你可以使用Gradle或Maven,從命令行運行應用程序。 或者,你可以構建一個包含所有依賴,類和資源的單個可執行JAR文件,並運行該文件。 這使得在整個開發生命周期中,可以很方便地跨不同的環境和版本,和部署服務成為一個應用程序。
如果你使用gradle, 你可以使用 ./gradlew bootRun
命令運行. 或者你可以使用 ./gradlew build
構建一個JAR . 然後你可以運行這個 JAR文件:
java -jar build/libs/gs-securing-web-0.1.0.jarn
如果你使用maven, 你可以使用 ./mvnw spring-boot:run
命令運行. 或者你可以使用 ./mvnw clean package
構建一個JAR. 然後你可以運行這個 JAR文件:
java -jar target/gs-securing-web-0.1.0.jarn
上述的過程將會創建一個可運行的JAR包. 你也可以在這兒獲知如何 構建一個傳統的WAR包.
... app starts up ...n
應用啟動後, 在瀏覽器中訪問 http://localhost:8080. 你可以訪問到首頁:
當你點擊鏈接,他將會讓你試圖去訪問 /hello
. 但因為該頁面是受保護的,所以你需要登錄, 於是來到了登錄頁面。
如果您使用未收保護的代碼版本訪問此處,那麼你將看不到此登錄頁面。 隨時備份和編寫其餘的受安全保護的代碼。
在登錄頁面,分別輸入用戶名和密碼欄位的」user」和」password」作為測試用戶登錄。 提交登錄表單後,你將進行身份認證,然後轉到問候頁面:
如果點擊「退出」按鈕,您的身份認證將被註銷,並返回到登錄頁面,並顯示一條消息,提示你已註銷。
總結
恭喜! 你已經開發了一個使用Spring Security保護的簡單Web應用程序。
發現
以下指南也可能有幫助:
- 使用SpringBoot構建應用程序
- 使用Spring MVC提供Web內容
- Spring Security 架構 (Reference guide)
- Spring Security and Angular JS (Tutorial)
作者:SpringForAll
鏈接:保護web應用的安全 | Spring For All聲明:本文轉載於SpringForAll,版權歸作者所有,有什麼問題,請聯繫我們,謝謝!
推薦閱讀:
※家居用品中有哪些安全隱患,需要大家注意,或是設計師進一步改善?
※如何進入安全公司實習或工作2--你該怎麼做?
※不用水的免洗洗手液,到底有沒有那麼神奇?
※2016阿里安全峰會重點資料下載
※修正液苯超標400倍 你還敢讓孩子用么?