[譯]Spring入門 - Web應用程序安全

原網頁 https://spring.io/guides/gs/securing-web/html

本指南將引導您完成建立一個資源由Spring Security的保護的一個簡單的Web應用程序的過程。java

你將構建

你將構建一個經過固定的用戶列表做爲後端的登陸表單來保護頁面安全的Spring MVC應用程序git

你將須要

  • 大約15分鐘github

  • 一個喜歡的文本編輯器或IDEweb

  • JDK 1.8 或更高版本spring

  • Gradle 2.3+ 或 Maven 3.0+數據庫

  • 你一樣能夠將本指南的代碼直接導入Spring Tool Suite (STS)並從這裏開始你的工做segmentfault

如何完成這個指南

如同大多數的Spring入門指南,你能夠從頭開始並完成每個步驟,或者能夠跳過這個你已經熟悉的基本配置過程。不管哪一種方式,您最終會得到可運行的代碼。後端

要從頭開始,請看「使用gradle構建」部分。瀏覽器

要跳過最基本的部分,按下面的步驟操做:

使用gradle構建

首先,你要建立一個基本的構建腳本。你可使用任何你喜歡的構建系統來構建Spring應用程序,可是你所須要的Gralde和Maven構建代碼已經包含在這裏了。若是你對二者都不熟悉,能夠參考「使用Gradle構建Java項目」或「使用Maven構建Java項目」。

建立目錄結構

你須要在你選的一個用做項目目錄的文件夾中,建立下面的子目錄結構;例如你能夠在*nix系統中使用mkdir -p src/main/java/hello這樣的命令來完成。

└── src
    └── main
        └── java
            └── hello

建立Gradle的build文件

下面是initial目錄下的Gradle的build文件(譯註:實際這個initial指的是項目的根目錄,它包含了上面所建立的src目錄,以及gradle.build文件,這樣執行gradle build命令時,gradle才能正確地找到要構建的代碼)。

文件名:build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.5.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'

jar {
    baseName = 'gs-securing-web'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile("org.springframework.boot:spring-boot-starter-thymeleaf")
    testCompile("junit:junit")
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.3'
}

使用maven構建

略,請參考原文

使用IDE構建

略,請參考原文

建立一個不安全的Web應用

在你能夠嘗試將安全性應用於Web應用以前,你須要一個用於「保護」的Web應用程序。本節中的步驟指導您完成建立一個很是簡單的Web應用程序。而後你將在下一節使用Spring Security將其保護起來。

這個web應用程序包括兩個簡單的視圖,一個是「主頁」,一個是「Hello World」頁。「主頁」的視圖由下面這個themeleaf模板來定義:

文件名:src/main/resources/templates/home.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security Example</title>
    </head>
    <body>
        <h1>Welcome!</h1>

        <p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
    </body>
</html>

如你所見,這個簡單的視圖包括一個指向「/hello」頁面的連接,它由下面這個themeleaf模板來定義:

src/main/resources/templates/hello.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Hello World!</title>
    </head>
    <body>
        <h1>Hello world!</h1>
    </body>
</html>

這個Web應用基於Spring MVC,所以你須要配置Spring MVC,而後設置view controller來暴露這些模板。下面就是一個配置好Spring MVC的Class。

文件名:src/main/java/hello/MvcConfig.java

package hello;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/home").setViewName("home");
        registry.addViewController("/").setViewName("home");
        registry.addViewController("/hello").setViewName("hello");
        registry.addViewController("/login").setViewName("login");
    }

}

addViewControllers()方法(覆蓋了WebMvcConfigurerAdapter的同名方法)添加了四個view controller。其中兩個view controller指向了「home」視圖(在home.html中定義),另外一個指向了「hello」視圖(在hello.html中定義)。第四個view controller指向另外一個視圖「login」,你將會在下個章節建立這個視圖。

此刻,你能夠直接跳到「讓Web應用可執行」的部分,在不須要任何登錄工做的狀況下運行Web應用。

一旦最基本的Web應用建立好了,你能夠給他加上安全防禦。

部署Spring Security

假設如今你但願防止未受權的用戶在輸入「/hello」這個網址後看到歡迎頁的內容。當前狀態下,若是用戶點擊「home」頁上的連接,他們能夠沒有任何阻礙地看到歡迎頁。如今你須要在用戶看到這個頁面前添加一個強制用戶登陸的阻礙。

你能夠經過配置Spring Security來完成上面所說的事。若是Spring Security在classpath中,SpringBoot會自動使用「基本」HTTP認證來保護全部HTTP端點,你也能夠進一步的定製安全設置。首先要作的事情就是把Spring Security加入到classpath中。

若是使用Gradle,它將會是dependencies部分中的一行:

文件名:build.gradle

dependencies {
    ...
    compile("org.springframework.boot:spring-boot-starter-security")
    ...
}

若是使用Maven,他將會是<dependencies>標籤中的一個子標籤:

文件名:pom.xml

<dependencies>
    ...
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
    ...
</dependencies>

下面是確保只有認證過的用戶才能看到「祕密的」歡迎頁的安全配置:

文件名:src/main/java/hello/WebSecurityConfig.java

package hello;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }
}

這個WebSecurityConfig類被@EnableWebMvcSecurity標註,來啓用Spring Security的web安全支持、以及提供與Spring MVC的融合。這個類還繼承了WebSecurityConfigurerAdapter並重寫了一些方法來指定一些特定的Web安全設置。

configure(HttpSecurity)方法規定了哪一個URL應該被保護,哪一個不該該。具體而言,「/」和「/home」的路徑被配置爲不須要任何認證。全部其餘URL必須進行身份驗證。

當用戶成功登陸後,他們將被重定向到先前請求的須要身份驗證的頁面。還有一個自定義(由loginPage()指定)的「/login」頁面,每一個用戶均可以查看。

對於configureGlobal(AuthenticationManagerBuilder)方法,它設置了一個單一用戶在內存中的用戶數據庫。該用戶被賦予「user」的用戶名,「password」的密碼,以及「USER」做爲角色。

如今,咱們須要建立登陸頁面。目前已經爲「login」視圖賦予了視圖控制器,因此你只須要建立login視圖自己:

文件名:src/main/resources/templates/login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security Example </title>
    </head>
    <body>
        <div th:if="${param.error}">
            Invalid username and password.
        </div>
        <div th:if="${param.logout}">
            You have been logged out.
        </div>
        <form th:action="@{/login}" method="post">
            <div><label> User Name : <input type="text" name="username"/> </label></div>
            <div><label> Password: <input type="password" name="password"/> </label></div>
            <div><input type="submit" value="Sign In"/></div>
        </form>
    </body>
</html>

正如你所看到的,這個Thymeleaf模板只是給出了一個採集用戶名和密碼,並將它們做爲請求post到「/login」的表單。正如剛剛配置的,Spring Security提供一個過濾器,截取該請求,並驗證用戶身份。若是用戶身份驗證失敗,頁面被重定向到「/login?error」,咱們的頁面將顯示相應的錯誤信息。一旦成功登出了,咱們的應用程序重定向到到「/login?logout」並顯示相應的登錄成功的消息。

最後,咱們須要給用戶提供一種方式來顯示當前用戶名和「Sign Out」按鈕。更新hello.html來問好當前用戶,幷包含一個「Sign Out」的按鈕,以下所示:

文件名:src/main/resources/templates/hello.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Hello World!</title>
    </head>
    <body>
        <h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
        <form th:action="@{/logout}" method="post">
            <input type="submit" value="Sign Out"/>
        </form>
    </body>
</html>

咱們經過使用Spring Security所集成的HttpServletRequest#getRemoteUser()來顯示用戶名。該「Sign Out」按鈕提交一個POST請求給「/logout」。一旦成功退出,將用戶重定向到「/login?logout」。

讓Web應用可執行

雖然能夠打包這項服務做爲一個傳統的web應用程序歸檔或WAR文件部署到外部應用服務器,下面展現了更簡單的方法來建立一個獨立的應用程序。你將打包一切到一個單一的,可執行的JAR文件中,用一個良好舊式Javamain()方法來調用。在此過程當中,你會用到Spring所支持的嵌入式Tomcat servlet容器做爲HTTP運行實例,而不是部署一個外部實例。

文件名:src/main/java/hello/Application.java

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) throws Throwable {
        SpringApplication.run(Application.class, args);
    }

}

@SpringBootApplication是個方便的註解,自動添加了全部如下內容:

  • @Configuration標記這個類做爲bean以定義應用程序上下文的來源。

  • @EnableAutoConfiguration告訴SpringBoot開始添加基於classpath設置,其餘Beans,以及各類屬性設置的Beans。

  • 一般狀況下你會給Spring MVC應用加上@EnableWebMvc註解,但當Spring Boot看到classpath中有spring-webmvc時,會自動添加這個註解。這標記該應用程序是一個Web應用程序,並激活一些關鍵行爲,好比建立一個DispatcherServlet

  • @ComponentScan告訴Spring去hello包中尋找其餘組件,配置,服務。

main()方法使用Spring Boot的SpringApplication.run()方法來啓動應用程序。你有沒有注意到,這裏沒有一行XML,一樣也沒有web.xml文件。這個Web應用程序是100%純Java寫的,你沒必要處理配置任何管道或基礎設施(譯註:plumbing or infrastructure,我這裏直譯了)。

構建一個可執行的JAR包

若是你正在使用gradle,你可使用./gradlew bootRun命令來運行應用程序。

你能夠構建一個包含全部必要的依賴,類和資源的一個可執行的JAR文件。這樣使傳輸,版本管理和部署服務在整個開發生命週期在不一樣的環境,等等,變得更容易

./gradlew build

而後你能夠這樣運行JAR包:

java -jar build/libs/gs-securing-web-0.1.0.jar

若是你正在使用Maven,你能夠經過mvn spring-boot:run來運行應用,或者你也能夠經過mvn clean package來構建JAR包,而後輸入下面的命令來運行:

java -jar target/gs-securing-web-0.1.0.jar

注意:上述過程將建立一個可運行的JAR。你也能夠選擇構建一個經典的WAR包來代替。

一旦應用程序啓動,用瀏覽器訪問http://localhost:8080。你應該看到主頁:

home

當你點擊這個連接,它會嘗試把你帶到/hello所指向的歡迎頁,但由於這個頁面是受保護的,並且目前爲止你沒有登陸,它會帶你到登錄頁

login

注意:若是你是直接從「不安全」的版本跳到這的,那麼你將不會看到登錄頁,請放鬆地回到上面寫完其他的基於安全的代碼

在登陸頁面,分別輸入「user」和「password」做爲用戶名和密碼,便可做爲測試用戶登陸。一旦你提交登陸表單,你會被進行身份驗證,而後帶你到歡迎頁:

welcome

若是你點擊「Sign Out」按鈕,你的身份驗證被撤銷,你將會返回到登陸頁並顯示一個消息提示你已經登出。

小結

恭喜你,你已經開發了一個簡單的、使用Spring Security來保護的Web應用。

想寫一個新的指南,或向已有的指南貢獻本身的能力?請看咱們的貢獻指南

相關文章
相關標籤/搜索