SpringBoot項目整合SpringSecurity

SpringSecurity官網介紹:

1 Spring Security是一個功能強大且高度可定製的身份驗證和訪問控制框架。它是用於保護基於Spring的應用程序的實際標準。
2 
3 Spring Security是一個框架,致力於爲Java應用程序提供身份驗證和授權。與所有Spring項目一樣,Spring Security的真正強大之處在於可以輕鬆擴展以滿足自定義要求

看了上面的介紹,可以知道SpringSecurity的主要功能就是:身份驗證 和 權限控制

下面帶大家進一步瞭解SpringSecurity的使用以及實現的過程

1、構建初始SpringBoot項目

1.1創建空項目

1.1.1選擇SpringBoot項目

1.1.2項目命名

 

 

 

 自動配置我們只選擇Spring Web,其餘的依賴自己來,爲了方便控制

 

 

 

 導入依賴

 1         <!--thymeleaf整合security-->
 2         <dependency>
 3             <groupId>org.thymeleaf.extras</groupId>
 4             <artifactId>thymeleaf-extras-springsecurity4</artifactId>
 5             <version>3.0.4.RELEASE</version>
 6         </dependency>
 7         <!--security -->
 8         <dependency>
 9             <groupId>org.springframework.boot</groupId>
10             <artifactId>spring-boot-starter-security</artifactId>
11         </dependency>
12         <!--thymeleaf-->
13         <dependency>
14             <groupId>org.thymeleaf</groupId>
15             <artifactId>thymeleaf-spring5</artifactId>
16         </dependency>
17         <dependency>
18             <groupId>org.thymeleaf.extras</groupId>
19             <artifactId>thymeleaf-extras-java8time</artifactId>
20         </dependency>
21         <!--以下爲系統系統自動導入,無需再次導入-->
22         <dependency>
23             <groupId>org.springframework.boot</groupId>
24             <artifactId>spring-boot-starter-web</artifactId>
25         </dependency>

好啦,現在總算把一個空項目新建完成了,接下來導入靜態資源,這裏我們提供一個網盤鏈接:

https://pan.baidu.com/s/1GlTmHAf2mmOuZc53Uf6jTQ
提取碼:ypxc

大家可以自取,都是一些簡單的頁面和項目所需的css,js

新建一個Controller自測一下:

 1 package com.ldk.controller;
 2 
 3 import org.springframework.stereotype.Controller;
 4 import org.springframework.web.bind.annotation.RequestMapping;
 5 import org.springframework.web.bind.annotation.ResponseBody;
 6 
 7 /**
 8  * @Author: ldk
 9  * @Date: 2020/5/19 21:44
10  * @Describe:
11  */
12 @Controller
13 public class testController {
14 
15     @RequestMapping("/hello")
16     @ResponseBody
17     public String hello(){
18         return "hello SpringSecurity";
19     }
20 }

 

項目總體結構如圖:

 

 

 啓動項目,訪問:http://localhost:8080/hello,又看到熟悉的:

 

 

 這證明這個簡單的Web項目可以跑通。

3、新建路由Controller

 

 1 package com.ldk.Controller;
 2 
 3 import org.springframework.stereotype.Controller;
 4 import org.springframework.web.bind.annotation.PathVariable;
 5 import org.springframework.web.bind.annotation.RequestMapping;
 6 
 7 /**
 8  * @Author: ldk
 9  * @Date: 2020/5/19 12:55
10  * @Describe:
11  */
12 @Controller
13 public class RouterController {
14 
15     @RequestMapping({"/","/index"})
16     public String index21(){
17         return "index";
18     }
19     @RequestMapping("/toLogin")
20     public String ind1ex(){
21         return "views/login";
22     }
23 
24     @RequestMapping("/level1/{id}")
25     public String ind1ex1(@PathVariable("id")int id){
26         return "views/level1/"+id;
27     }
28     @RequestMapping("/level2/{id}")
29     public String ind1ex2(@PathVariable("id")int id){
30         return "views/level2/"+id;
31     }
32     @RequestMapping("/level3/{id}")
33     public String ind1ex3(@PathVariable("id")int id){
34         return "views/level3/"+id;
35     }
36 
37 }

 

 

 

4、上主菜(配置SecurityConfig)

我們都知道,無論SpringBoot或者SpringCloud與其他框架集成,都必須先導包,在創建Config類進行配置,然後加一個類似於@Enablexxx的註解,即可使用,SpringBoot集成SpringSecurity也不例外,這一步我們先創建一個空的SecurityConfig類  並集成 WebSecurityConfigurerAdapter 類,並重寫他裏面的兩個方法,這裏我們解釋一下:WebSecurityConfigurerAdapter 類是個適配器, 在配置的時候,需要我們自己寫個配置類去繼承他,然後編寫自己所特殊需要的配置,我們重寫一下它的 認證 和 授權 方法,來實現自己的定製化個性服務。

在SpringSecurityApplication同級目錄下新建config文件夾,並新建SecurityConfig配置類:

 1 package com.ldk.config;
 2 
 3 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
 4 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 5 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 6 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 7 
 8 /**
 9  * @Author: ldk
10  * @Date: 2020/5/19 13:38
11  * @Describe:
12  */
13 
14 @EnableWebSecurity
15 public class SecurityConfig extends WebSecurityConfigurerAdapter {
16 
17     //授權
18     @Override
19     protected void configure(HttpSecurity http) throws Exception {
20     }
21 
22     //認證
23     @Override
24     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
25     }
26 
27 }

。現在訪問以下http://localhost:8080/  順利跳轉首頁,這個時候,首頁的level1,level2,level3頁面均可以有權限訪問

 

 

下面我們通過操作SecurityConfig配置類,來做一些定製化需求實現

1、首頁我都允許訪問,但是level1、level2、level3頁面均需要獲取對應的vip1,vip2,vip3權限後纔可以訪問,沒有權限跳轉定製的登錄頁面

在授權方法加入授權規則:

    //授權
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //首頁所有人可以訪問,但是裏面的功能頁,只有對應有權限的人才能訪問
        //鏈式編程
        //請求授權的規則
        http.authorizeRequests().antMatchers("/").permitAll().
                antMatchers("/level1/**").hasRole("vip1").
                antMatchers("/level2/**").hasRole("vip2").
                antMatchers("/level3/**").hasRole("vip3");
        //沒有權限 跳轉登錄頁,需要開啓登錄頁面
        //定製登錄頁
        http.formLogin().loginPage("/toLogin");
        //這裏我們也可以只寫http.formLogin();這樣他就會跳轉到/login,這個頁面時SprignSecurity爲我們準備好的登錄頁面
    }

現在重啓項目,發現只有首頁能訪問,其他頁面都會自動跳轉到我們自己編寫的登錄頁面:

 

 

 

我們只是做了一些簡單的配置工作,SpringSecurity在底層已經爲我們做好了一切,框架就是這樣,拿來就用,如果自己想明白原理,可以點進去源碼研究一下。

 

接下來我們要實現指定用戶能訪問某些頁面,就要修改身份認證的配置方法,這裏的用戶名密碼需要從數據庫查詢,我們就用幾組死數據代表了:

    //認證
    //密碼編碼 passwordEncoder
    //在SpringSecurity 5.x中  新增了很多加密方法
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //正常這些數據應該從數據庫讀取
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("kuangshen").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
                .and().withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
                .and()
                .withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1");
    }

需要注意的是我們在密碼外面包裹了一層 BCryptPasswordEncoder.encod方法,這是SprignSecurity的一個密碼校驗,現在重啓項目,在登錄頁面輸入我們設定的賬號密碼,神奇的發現,頁面確實進行了授權。

註銷及權限控制:

想實現註銷按鈕,首先在首頁添加一個註銷按鈕:

修改授權配置類,開啓註銷功能:

    //授權
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //首頁所有人可以訪問,但是裏面的功能頁,只有對應有權限的人才能訪問
        //鏈式編程
        //請求授權的規則
        http.authorizeRequests().antMatchers("/").permitAll().
                antMatchers("/level1/**").hasRole("vip1").
                antMatchers("/level2/**").hasRole("vip2").
                antMatchers("/level3/**").hasRole("vip3");
        //沒有權限 跳轉登錄頁,需要開啓登錄頁面
        //定製登錄頁
//        http.formLogin().loginPage("/toLogin");
        http.formLogin();
        //這裏我們也可以只寫http.formLogin();這樣他就會跳轉到/login,這個頁面時SprignSecurity爲我們準備好的登錄頁面
        //開啓註銷功能
        //防止網站攻擊   csrf 防止
        // 跨站攻擊(代碼是配置死的)
        http.csrf().disable();
        http.logout().logoutSuccessUrl("/");
    }

下面進行權限的控制,我們想讓用戶登錄成功之後只可以看到自己可以看到的頁面,自己沒有權限的頁面看不到,這個需要在前端index頁面做手腳即可,我們一開始已經集成了 thymeleaf整合security 的包,直接判斷用戶是否登陸,就可以校驗出用戶是否有權限。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>首頁</title>
    <!--semantic-ui-->
    <link href="https://cdn.bootcss.com/semantic-ui/2.4.1/semantic.min.css" rel="stylesheet">
    <link th:href="@{/qinjiang/css/qinstyle.css}" rel="stylesheet">
</head>
<body>

<!--主容器-->
<div class="ui container">

    <div class="ui segment" id="index-header-nav" th:fragment="nav-menu">
        <div class="ui secondary menu">
            <a class="item" th:href="@{/index}">首頁</a>

            <!--登錄註銷-->
            <div class="right menu">


                <!--未登錄 顯示登錄按鈕-->
                <div sec:authorize="!isAuthenticated()">
                    <a class="item" th:href="@{/toLogin}">
                        <i class="address card icon"></i> 登錄
                    </a>
                </div>


                <!--已登錄 顯示註銷按鈕 和用戶名-->
                <div sec:authorize="isAuthenticated()">
                    <a class="item">
                        用戶名:<span sec:authentication="name"></span>
                    </a>
                </div>
                <div sec:authorize="isAuthenticated()">
                    <a class="item" th:href="@{/logout}">
                        <i class="sign-out card icon"></i> 註銷
                    </a>
                </div>

                <!--已登錄
                <a th:href="@{/usr/toUserCenter}">
                    <i class="address card icon"></i> admin
                </a>
                -->
            </div>
        </div>
    </div>

    <div class="ui segment" style="text-align: center">
        <h3>Spring Security Study by DK</h3>
    </div>

    <div>
        <br>
        <div class="ui three column stackable grid">
            <!--菜單根據用戶角色進行顯示-->
            <div class="column" sec:authorize="hasRole('vip1')">
                <div class="ui raised segment">
                    <div class="ui">
                        <div class="content">
                            <h5 class="content">Level 1</h5>
                            <hr>
                            <div><a th:href="@{/level1/1}"><i class="bullhorn icon"></i> Level-1-1</a></div>
                            <div><a th:href="@{/level1/2}"><i class="bullhorn icon"></i> Level-1-2</a></div>
                            <div><a th:href="@{/level1/3}"><i class="bullhorn icon"></i> Level-1-3</a></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="column" sec:authorize="hasRole('vip2')">
            <div class="ui raised segment">
                <div class="ui">
                    <div class="content">
                        <h5 class="content">Level 2</h5>
                        <hr>
                        <div><a th:href="@{/level2/1}"><i class="bullhorn icon"></i> Level-2-1</a></div>
                        <div><a th:href="@{/level2/2}"><i class="bullhorn icon"></i> Level-2-2</a></div>
                        <div><a th:href="@{/level2/3}"><i class="bullhorn icon"></i> Level-2-3</a></div>
                    </div>
                </div>
            </div>
        </div>
        <div class="column" sec:authorize="hasRole('vip3')">
            <div class="ui raised segment">
                <div class="ui">
                    <div class="content">
                        <h5 class="content">Level 3</h5>
                        <hr>
                        <div><a th:href="@{/level3/1}"><i class="bullhorn icon"></i> Level-3-1</a></div>
                        <div><a th:href="@{/level3/2}"><i class="bullhorn icon"></i> Level-3-2</a></div>
                        <div><a th:href="@{/level3/3}"><i class="bullhorn icon"></i> Level-3-3</a></div>
                    </div>
                </div>
            </div>
        </div>

    </div>
</div>

</div>


<script th:src="@{/qinjiang/js/jquery-3.1.1.min.js}"></script>
<script th:src="@{/qinjiang/js/semantic.min.js}"></script>

</body>
</html>

主要是添加了 thymeleaf的空間域名,寫代碼的時候 會有提示,並且保證語法不報錯

現在訪問頁面,發現首頁的菜單已經很好的被控制住了,只能顯示經過我們授權後的菜單鏈接。

 

 

以上代碼均來自於狂神,bilibili鏈接:https://space.bilibili.com/95256449,大家可以去網站找到對應的教學視頻。再一次感謝狂神。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章