SpringBoot整合Spring Security

2020-09-21 15:00:24

Spring Security是一個安全框架,因為現在對於我們開發來講安全是十分重要的。
在java領域我們主要用的兩個安全框架,一個是Shiro,一個是Spring Security,Shiro因為它的一個輕量級的特性我們用的比較多,Spring Security相比於Shiro屬於重量級的一個框架,但是它的功能要比Shiro強大很多,同時它的許可權控制也更加細化,Spring Security是Spring家族的一個產品,可以跟我們的Spring應用很好的整合到一塊,就不需要去做額外的整合了。

安全框架其實就是對使用者端存取的一個許可權控制。

我們之前寫的如果我們要存取一個首頁,存取首頁使用者必須得先登入,它得是一個登入狀態,我們之前是怎麼判斷的呢(我們之前是加了一個過濾器),然後對請求進行了攔截,攔截完成之後判斷session是否存在,如果存在就讓它繼續往後走,如果不存在就直接給它返回到登入頁面。這個實際上就是一個許可權控制。

Spring Security就是自動幫我們完成這個許可權控制的。(用了這個框架以後我們就不需要自己去寫過濾器了,它會自動幫我們進行各種各樣的驗證)。

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.southwind</groupId>
    <artifactId>springbootspringsecurity22</artifactId>
    <version>1.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

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

        <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>
    </dependencies>

</project>

2.建立Handler
在這裡插入圖片描述

package com.southwind.controller;

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

@Controller
public class HelloHandler {
    @GetMapping("/index")
    public String index(){
        return "index";
    }
}

3.建立html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>世界你好</h1>
</body>
</html>

4.建立組態檔applicatiom.yml

spring:
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html

5.建立啟動類

package com.southwind.controller;

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

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

預設的使用者名稱是user

spring:
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
  security:
    user:
      name: admin
      password: 123123

接下來我們來看它最核心的東西:許可權管理
在實際開發中我們一般不會直接將許可權和使用者繫結。(實際開發中我們會將許可權賦給角色,角色賦給使用者)

在這裡插入圖片描述定義兩個HTML資源:index.html,admin.html,同時定義兩個角色ADMIN(管理員兩個都可以存取)和USER(使用者只可以存取index.html)

7.建立SecurityConfig類。
在這裡插入圖片描述

package com.southwind.config;

import org.springframework.security.crypto.password.PasswordEncoder;

public class MyPasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence charSequence) {
        return charSequence.toString();
    }

    @Override
    public boolean matches(CharSequence charSequence, String s) {
        return s.equals(charSequence.toString());
    }
}

package com.southwind.config;

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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration  //表示它是設定的一個類
@EnableWebSecurity  //讓WebSecurity生效
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //用來新增賬戶和角色
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().passwordEncoder(new MyPasswordEncoder())
                .withUser("user").password(new MyPasswordEncoder().encode("000")).roles("USER")
                .and()
                .withUser("admin").password(new MyPasswordEncoder().encode("123")).roles("ADMIN","USER");

    }
    //用來設定角色和許可權的關係
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/admin").hasRole("ADMIN")
                .antMatchers("/index").access("hasRole('ADMIN') or hasRole('USER')")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
                .logout()
                .permitAll()
                .and()
                .csrf()
                .disable();
    }
}

8.修改Handler

package com.southwind.controller;

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

@Controller
public class HelloHandler {
    //用來存取資源
    @GetMapping("/index")
    public String index(){
        return "index";
    }
    //用來存取資源
    @GetMapping("/admin")
    public String admin(){
        return "admin";
    }
    //用來做登入的
    @GetMapping("/login")
    public String login(){
        return "login";
    }
}

9.login.html

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

</body>
</html>

10.index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>世界你好</h1>
<form action="/logout" method="post">
    <input type="submit" value="退出">
</form>
</body>
</html>

11.admin.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>後臺管理系統</h1>
<form action="/logout" method="post">
    <input type="submit" value="退出">
</form>

</body>
</html>

舉例當我存取index時候會先跳轉到login,然後通過controller跳轉到自己寫的login.html,然後點選表單把資料提交到Spring Securiry的login,然後才會到達index.html