《Spring Security 實戰》學習:建立簡單的Spring Security項目

參考教程:陳木鑫老師的《Spring Security 實戰》html

建立spring boot項目

經過Intellij IDEA建立Spring Boot項目的方式有許多種,其中最簡單的方式就是使用Spring Initializr
工具。
Spring Initializr 容許咱們提早選定一些經常使用的項目依賴,此處咱們選擇 Security 做爲構建Spring
Security項目的最小依賴,選擇Web做爲Spring Boot構建Web應用的核心依賴。
在這裏插入圖片描述
Next :
在這裏插入圖片描述
Next:
在這裏插入圖片描述
建立項目的目錄結構:
在這裏插入圖片描述前端

maven 引用

在自動構建的Spring Security 項目中,Spring Initializr 爲咱們引入瞭如下依賴:java

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

咱們點開spring-boot-starter-security能夠看到,其包含了如下依賴:web

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>2.3.1.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-config</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-web</artifactId>
      <scope>compile</scope>
    </dependency>

其中 spring-security-webspring-security-config兩個核心模塊,正是官方建議引入的Spring Security最小依賴。spring

聲明controller

在項目中聲明一個測試路由TestController後端

package com.haan.springsecuritydemo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @GetMapping
    public String hello(){
        return "Hello Spring Security!";
    }
}

在這裏插入圖片描述

運行SpringsecuritydemoApplication

運行SpringsecuritydemoApplication,默認啓動 8080 端口,打開瀏覽器,訪問localhost:8080,咱們發現頁面跳轉到了localhost:8080/login:
在這裏插入圖片描述
在引入Spring Security項目以後,雖然沒有進行任何相關的配置或編碼,但Spring Security有一個默認的運行狀態,要求在通過表單基本認證後才能訪問對應的URL資源,其默認使用的用戶名爲 user ,密碼則是動態生成並打印到控制檯的一串隨機碼。翻看控制檯的打印信息:
在這裏插入圖片描述
輸入用戶名和密碼後,單擊「登陸」按鈕便可成功訪問:
在這裏插入圖片描述瀏覽器

修改登陸信息

基本表單認證中,用戶名和密碼都是能夠配置的,最多見的就是在resources下的application配置文件中修改:安全

spring.security.user.name=user02
spring.security.user.password=aaaaaa

從新啓動程序,發現控制檯再也不打印默認密碼串了,此時使用咱們自定義的用戶名和密碼便可登陸。服務器

WebSecurityConfigurerAdapter

protected void configure(HttpSecurity http) throws Exception {
        this.logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");
        ((HttpSecurity)((HttpSecurity)((AuthorizedUrl)http.authorizeRequests().anyRequest()).authenticated().and()).formLogin().and()).httpBasic();
    }

能夠看到 WebSecurityConfigurerAdapter 已經默認聲明瞭一些安全特性:app

  • 驗證全部請求。
  • 容許用戶使用表單登陸進行身份驗證(Spring Security 提供了一個簡單的表單登陸頁面)。
  • 容許用戶使用HTTP 基本認證。

spring boot 默認定義了DefaultConfigurerAdapter ,由@ConditionalOnMissingBean可知當沒有其餘WebSecurityConfigurerAdapter被定義時,將使用DefaultConfigurerAdapter

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnClass({WebSecurityConfigurerAdapter.class})
@ConditionalOnMissingBean({WebSecurityConfigurerAdapter.class})
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
public class SpringBootWebSecurityConfiguration {
    public SpringBootWebSecurityConfiguration() {
    }

    @Configuration(
        proxyBeanMethods = false
    )
    @Order(2147483642)
    static class DefaultConfigurerAdapter extends WebSecurityConfigurerAdapter {
        DefaultConfigurerAdapter() {
        }
    }
}

自定義表單登陸頁

Spring boot提供了WebSecurityConfigurerAdapter 的默認實現DefaultConfigurerAdapter,可以提供基本表單登陸認證。

雖然自動生成的表單登陸頁能夠方便、快速地啓動,可是大多數應用程序更但願提供本身的表單登陸頁,此時就須要咱們提供本身的WebSecurityConfigurerAdapter來代替DefaultConfigurerAdapter,覆寫WebSecurityConfigurerAdapterconfigure方法:

@EnableWebSecurity
public class MyWebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/myLogin.html")    //指明登陸頁面
                .permitAll()    //指明登陸頁容許全部進行訪問
                .and()
                .csrf().disable();
    }
}
  • authorizeRequests()方法實際上返回了一個 URL 攔截註冊器,咱們能夠調用它提供的anyRequest()antMatchers()regexMatchers()等方法來匹配系統的URL,併爲其指定安全策略。
  • formLogin()方法和httpBasic()方法都聲明瞭須要Spring Security提供的表單認證方式,分別返回對應的配置器。其中formLogin().loginPage("/myLogin.html")指定自定義的登陸

/myLogin.html,同時,Spring Security會用/myLogin.html註冊一個POST路由,用於接收登陸請求。

  • csrf()方法是Spring Security提供的跨站請求僞造防禦功能,當咱們繼承WebSecurityConfigurer Adapter時會默認開啓 csrf()方法。

訪問localhost:8080 ,咱們發現,頁面就跳轉到了localhost:8080/myLogin.html,因爲咱們靜態文件中並無myLogin.html 文件,因此提示了一個404的white page:
在這裏插入圖片描述
咱們在resources/static 文件夾下建立頁面myLogin.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello Security!</title>
</head>
<body>
    <h3>登陸頁</h3>
    <form action="/myLogin.html" method="post">
        <input type="text" name="username"> <br/>
        <input type="text" name="password"> <br/>
        <input type="submit" value="login">
    </form>
</body>
</html>

重啓服務,再次訪問localhost:8080:
在這裏插入圖片描述
輸入上面的application.properties中配置的用戶登陸帳戶和密碼進行登陸,登錄成功:
在這裏插入圖片描述

其餘表單配置項

指定登陸處理URL

在自定義表單登陸頁以後,處理登陸請求的URL也會相應改變,默認狀況下,
若是隻配置loginPage而不配置loginProcessingUrl的話那麼loginProcessingUrl默認就是loginPage,若是須要自定義登陸請求的URL,須要配置loginProcessingUrl:

重啓登陸,咱們發現中間訪問了localhost:8080/myLogin
在這裏插入圖片描述

補充:loginPageloginProcessingUrl

  • 二者都不配置:默認都是/login
  • 二者都配置:按本身的來
  • 只配置loginProcessingUrlloginPage默認/login
  • 只配置loginPage: loginProcessingUrl默認就是loginPage

設置登陸成功處理

此時,有些讀者可能會有疑問,由於按照慣例,在發送登陸請求並認證成功以後,頁面會跳轉回原訪問頁。在某些系統中的確是跳轉回原訪問頁的,但在部分先後端徹底分離、僅靠JSON完成全部交互的系統中,通常會在登陸時返回一段 JSON 數據,告知前端成功登陸成功與否,由前端決定如何處
理後續邏輯,而非由服務器主動執行頁面跳轉。這在Spring Security中一樣能夠實現。

表單登陸配置模塊提供了 successHandler()failureHandler()兩個方法,分別處理登陸成功和登陸失敗的邏輯。

  • successHandler()方法帶有一個Authentication參數,攜帶當前登陸用戶名及其角色等信息;
  • failureHandler()方法攜帶一個AuthenticationException異常參數。具體處理方式需按照系統的狀況自定義。
@EnableWebSecurity
public class MyWebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/myLogin.html") //指明登陸頁面
                .loginProcessingUrl("/myLogin")   //指明處理登錄的URL路徑,即登錄表單提交請求
                .successHandler(new AuthenticationSuccessHandler() {        // 設置登陸成功的處理器
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                        PrintWriter responseWriter = httpServletResponse.getWriter();
                        String name = authentication.getName();
                        responseWriter.write(name+" login success!");
                    }
                })
                .failureHandler(new AuthenticationFailureHandler() {        // 設置登陸失敗的處理器
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                        PrintWriter responseWriter = httpServletResponse.getWriter();
                        responseWriter.write("login error!");
                    }
                })
                .permitAll()    //指明登陸頁容許全部進行訪問
                .and()
                .csrf().disable();
    }
}

正確的帳號密碼:
在這裏插入圖片描述
錯誤的帳號密碼:
在這裏插入圖片描述

相關文章
相關標籤/搜索