首頁 > 軟體

SpringSecurity自定義登入介面

2022-09-06 18:06:48

為什麼需要自定義登入介面?

答:因為SpringBoot整合SpringSecurity時,只需要一個依賴,無需其他設定,就可以實現認證功能。但是它的認證登入介面是固定那樣的,如下圖所示,但是我們希望自己搞個好看的登入介面,所以需要自定義登入介面。

第一步:建立springboot專案

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-security-03</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-security-03</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--thymeleaf-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

第二步:新增設定application.properties

#修改springSecurity預設使用者名稱和密碼
spring.security.user.name=root
spring.security.user.password=root

#設定 thymeleaf 快取為false,表示立即生效
spring.thymeleaf.cache=false

第三步:Controller

package com.example.controller;

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

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String hello(){
        System.out.println("hello spring security");
        return "hello spring security";
    }
}
package com.example.controller;

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

@RestController
public class IndexController {

    @RequestMapping("/index")
    public String hello(){
        System.out.println("hello index");
        return "hello index";
    }
}
package com.example.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class LoginController {

    @RequestMapping("/loginHtml")
    public String loginHtml(){
        return "login";
    }
}

第四步:login.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org/" lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用者登入</title>
</head>
<body>
    <h1>使用者登入</h1>
    <form th:action="@{/doLogin}" method="post">
        使用者名稱:<input type="text" name="username"> <br>
        密碼:<input type="text" name="password"><br>
        <input type="submit" value="登入">
    </form>
</body>
</html>

第五步:設定自定義登入介面

package com.example.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {


    @Override
    public void configure(HttpSecurity http) throws Exception {

        //【注意事項】放行資源要放在前面,認證的放在後面
        http.authorizeRequests()
                .mvcMatchers("/index").permitAll() //代表放行index的所有請求
                .mvcMatchers("/loginHtml").permitAll() //放行loginHtml請求
                .anyRequest().authenticated()//代表其他請求需要認證
                .and()
                .formLogin()//表示其他需要認證的請求通過表單認證
                //loginPage 一旦你自定義了這個登入頁面,那你必須要明確告訴SpringSecurity日後哪個url處理你的登入請求
                .loginPage("/loginHtml")//用來指定自定義登入介面,不使用SpringSecurity預設登入介面  注意:一旦自定義登入頁面,必須指定登入url
                //loginProcessingUrl  這個doLogin請求本身是沒有的,因為我們只需要明確告訴SpringSecurity,日後只要前端發起的是一個doLogin這樣的請求,
                //那SpringSecurity應該把你username和password給捕獲到
                .loginProcessingUrl("/doLogin")//指定處理登入的請求url
                .and()
                .csrf().disable(); //禁止csrf 跨站請求保護
    }
}

5.1 請求引數名修改

上面的login.html使用者名稱必須為username,密碼必須為password,如果我們想要使用自定義的屬性名,按照如下修改

5.1.1 修改login.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org/" lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用者登入</title>
</head>
<body>
    <h1>使用者登入</h1>
    <form th:action="@{/doLogin}" method="post">
        使用者名稱:<input type="text" name="uname"> <br>
        密碼:<input type="text" name="passwd"><br>
        <input type="submit" value="登入">
    </form>
</body>
</html>

5.1.2 修改設定類

package com.example.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {


    @Override
    public void configure(HttpSecurity http) throws Exception {

        //【注意事項】放行資源要放在前面,認證的放在後面
        http.authorizeRequests()
                .mvcMatchers("/index").permitAll() //代表放行index的所有請求
                .mvcMatchers("/loginHtml").permitAll() //放行loginHtml請求
                .anyRequest().authenticated()//代表其他請求需要認證
                .and()
                .formLogin()//表示其他需要認證的請求通過表單認證
                //loginPage 一旦你自定義了這個登入頁面,那你必須要明確告訴SpringSecurity日後哪個url處理你的登入請求
                .loginPage("/loginHtml")//用來指定自定義登入介面,不使用SpringSecurity預設登入介面  注意:一旦自定義登入頁面,必須指定登入url
                //loginProcessingUrl  這個doLogin請求本身是沒有的,因為我們只需要明確告訴SpringSecurity,日後只要前端發起的是一個doLogin這樣的請求,
                //那SpringSecurity應該把你username和password給捕獲到
                .loginProcessingUrl("/doLogin")//指定處理登入的請求url
                .usernameParameter("uname") //指定登入介面使用者名稱文字方塊的name值,如果沒有指定,預設屬性名必須為username
                .passwordParameter("passwd")//指定登入介面密碼密碼框的name值,如果沒有指定,預設屬性名必須為password
                .and()
                .csrf().disable(); //禁止csrf 跨站請求保護
    }
}

5.1 認證成功跳轉路徑

修改設定類successForwardUrl

package com.example.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {


    @Override
    public void configure(HttpSecurity http) throws Exception {

        //【注意事項】放行資源要放在前面,認證的放在後面
        http.authorizeRequests()
                .mvcMatchers("/index").permitAll() //代表放行index的所有請求
                .mvcMatchers("/loginHtml").permitAll() //放行loginHtml請求
                .anyRequest().authenticated()//代表其他請求需要認證
                .and()
                .formLogin()//表示其他需要認證的請求通過表單認證
                //loginPage 一旦你自定義了這個登入頁面,那你必須要明確告訴SpringSecurity日後哪個url處理你的登入請求
                .loginPage("/loginHtml")//用來指定自定義登入介面,不使用SpringSecurity預設登入介面  注意:一旦自定義登入頁面,必須指定登入url
                //loginProcessingUrl  這個doLogin請求本身是沒有的,因為我們只需要明確告訴SpringSecurity,日後只要前端發起的是一個doLogin這樣的請求,
                //那SpringSecurity應該把你username和password給捕獲到
                .loginProcessingUrl("/doLogin")//指定處理登入的請求url
                .usernameParameter("uname") //指定登入介面使用者名稱文字方塊的name值,如果沒有指定,預設屬性名必須為username
                .passwordParameter("passwd")//指定登入介面密碼密碼框的name值,如果沒有指定,預設屬性名必須為password
                .successForwardUrl("/index")//認證成功 forward 跳轉路徑
                .and()
                .csrf().disable(); //禁止csrf 跨站請求保護
    }
}

修改設定類defaultSuccessUrl

package com.example.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {


    @Override
    public void configure(HttpSecurity http) throws Exception {

        //【注意事項】放行資源要放在前面,認證的放在後面
        http.authorizeRequests()
                .mvcMatchers("/index").permitAll() //代表放行index的所有請求
                .mvcMatchers("/loginHtml").permitAll() //放行loginHtml請求
                .anyRequest().authenticated()//代表其他請求需要認證
                .and()
                .formLogin()//表示其他需要認證的請求通過表單認證
                //loginPage 一旦你自定義了這個登入頁面,那你必須要明確告訴SpringSecurity日後哪個url處理你的登入請求
                .loginPage("/loginHtml")//用來指定自定義登入介面,不使用SpringSecurity預設登入介面  注意:一旦自定義登入頁面,必須指定登入url
                //loginProcessingUrl  這個doLogin請求本身是沒有的,因為我們只需要明確告訴SpringSecurity,日後只要前端發起的是一個doLogin這樣的請求,
                //那SpringSecurity應該把你username和password給捕獲到
                .loginProcessingUrl("/doLogin")//指定處理登入的請求url
                .usernameParameter("uname") //指定登入介面使用者名稱文字方塊的name值,如果沒有指定,預設屬性名必須為username
                .passwordParameter("passwd")//指定登入介面密碼密碼框的name值,如果沒有指定,預設屬性名必須為password
//                .successForwardUrl("/index")//認證成功 forward 跳轉路徑,forward代表伺服器內部的跳轉之後,位址列不變 始終在認證成功之後跳轉到指定請求
                .defaultSuccessUrl("/index")//認證成功 之後跳轉,重定向 redirect 跳轉後,地址會發生改變  根據上一儲存請求進行成功跳轉
                .and()
                .csrf().disable(); //禁止csrf 跨站請求保護
    }
}

存取http://localhost:8080/hello,認證後

發現並沒有到/index的情況,這是defaultSuccessUrl一特性,如果你想硬跳到/index,修改java defaultSuccessUrl("/index",true)即可

存取http://localhost:8080/loginHtml,認證後

defaultSuccessUrl和successForwardUrl區別

1、successForwardUrl是forward跳轉,defaultSuccessUrl是重定向redirect跳轉
2、successForwardUrl始終在認證成功之後跳轉到指定請求,defaultSuccessUrl根據上一儲存請求進行成功跳轉

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com