天天看點

Spring Boot Security 實作背景&權限管理系統(一)

廢話連篇

Hi!各位部落格大佬們,初來乍到,本人是工齡僅有一年半載的初級程式員(俗稱:菜鳥),說來慚愧,距今接觸Java開發已有了近兩年之久,可時間越往後挪我就越發感到惶恐不安,很多次甚至反思自己到底是不是能夠從事該行業,幾經輾轉發現了自身一個問題,就是無論做什麼都隻在腦子裡過一遍,卻從不做任何筆記、流程圖等。是以,從這裡開始,就通過部落格的方式記錄下自己的一言一行,一是為了提升自己,二是為了供後來的初學者所參考,避免踩坑!由于自身能力有限,該部落格如有任何問題,還請大佬們多多包涵及指正!

1、Spring Boot Security

Spring Boot Security 實作背景&權限管理系統(一)

如圖,是一種通用的使用者權限模型。一般情況下會有5張表,分别是:使用者表,角色表,權限表,使用者角色關系表,角色權限對應表。

一般,資源配置設定時是基于角色的(即,資源通路權限賦給角色,使用者通過角色進而擁有權限);而通路資源的時候是基于資源權限去進行授權判斷的。

Spring Security和Apache Shiro是兩個應用比較多的權限管理架構。Spring Security依賴Spring,其功能強大,相對于Shiro而言學習難度稍大一些。

Spring的強大是不言而喻的,可擴充性也很強,強大到用Spring家族的産品隻要按照其推薦的做法來就非常非常簡單,否則,自己去整合過程可能會很痛苦。

目前,我們項目是基于Spring Boot的,而且Spring Boot的權限管理也是推薦使用Spring Security的,是以再難也是要學習的。

1.1、Spring Security 簡介

Spring Security緻力于為Java應用提供認證和授權管理。它是一個強大的,高度自定義的認證和通路控制架構。

具體介紹參見 https://docs.spring.io/spring-security/site/docs/5.0.5.RELEASE/reference/htmlsingle/

這句話包括兩個關鍵詞:Authentication(認證)和 Authorization(授權,也叫通路控制)

認證是驗證使用者身份的合法性,而授權是控制你可以做什麼。

簡單地來說,認證就是你是誰,授權就是你可以做什麼。

1.2、Spring Security接口介紹

  • AuthenticationManager
    Spring Boot Security 實作背景&權限管理系統(一)
    在這裡不過多講述,有興趣的小夥伴可以看看AuthenticationManager原理
  • AuthenticationProvider
    Spring Boot Security 實作背景&權限管理系統(一)
    AuthenticationProvider接口是用于認證的,可以通過實作這個接口來定制我們自己的認證邏輯,它的實作類有很多,預設的是JaasAuthenticationProvider,它的全稱是Java Authentication and Authorization Service (JAAS),常用的是AbstractUserDetailsAuthenticationProvider以及它的子類DaoAuthenticationProvider。
  • AccessDecisionManager
    Spring Boot Security 實作背景&權限管理系統(一)
    AccessDecisionManager做處最終的通路控制決策,故名思義,它決定了使用者是否可以通路某個資源,是以,我們可以實作AccessDecisionManager用于定制我們自己的授權邏輯。
  • AccessDecisionVoter
    Spring Boot Security 實作背景&權限管理系統(一)
    AccessDecisionVoter投票器,在授權時通過投票的方式決定使用者是否具有權限,這裡涉及到了三種投票規則,AffirmativeBased如果有一票通過,則視為有權通路,ConsensusBased多數表決(少從多),如果有多數表決通過,則有權通路,反之無權通路。UnanimousBased如果有一票投了否決,則直接視為無權通路。
  • UserDetailsService
    Spring Boot Security 實作背景&權限管理系統(一)
    UserDetailsService使用者詳細資訊服務接口,該接口中隻存在一個方法loadUserByUsername() 該方法通過指定的使用者名用來擷取UserDetails,通常在Security應用中,我們會自定義一個接口用來實作它,并與之與資料庫進行互動。

內建Spring Security

接下來的方式,我們都按照官方文檔的方式來進行配置,即我們需要在配置檔案中添加UserDetailsService, AuthenticationProvider, or AuthenticationManager這幾種類型的Bean。

這裡我使用到了SpringBoot多子產品,主要目的是多子產品的劃分可以降低代碼之間的耦合性(從類級别的耦合提升到jar包級别的耦合),每個子產品都可以是自解釋的(通過子產品名或者子產品文檔),子產品還規範了代碼邊界的劃分。

SpringBoot多子產品建構

我們按照SpringBoot多子產品建構完畢後,我的項目結構如下:

Spring Boot Security 實作背景&權限管理系統(一)
子產品 說明
bpms-permission-api 項目接口服務層,包涵Java實體、資料互動接口(dao)及服務接口(service)
bpms-permission-common 公共服務層,主要包涵一些工具類、常量、過濾器、攔截器等
bpms-permission-management 權限層,和權限有關的都在這裡面。
bpms-permission-service 項目接口服務實作層,mybatis的XML檔案以及接口實作
bpms-permission-web 項目視圖控制層,包含前端部分和控制器

建構完成之後,删除多餘檔案,確定除了bpms-permission-web子產品,其餘子產品的結構如下圖所示:

Spring Boot Security 實作背景&權限管理系統(一)

maven依賴

多子產品在引入maven時需要注意,盡量把所有的maven依賴都放置在父pom檔案下,其他子產品需要用的依賴再引用即可。

  • 父級子產品(bpms2.0)maven配置如下:
<?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.2.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.zlx</groupId>
    <artifactId>bpms2.0</artifactId>
    <version>1.0.1-SNAPSHOT</version>
    <name>bpms</name>
    <!--父級項目的packaging設定為pom-->
    <packaging>pom</packaging>
    <description>SpringBoot父工程</description>
    <!--主工程包含子子產品工廠配置-->
    <modules>
        <module>bpms</module>
    </modules>
    <!--配置參數-->
    <properties>
        <java.version>1.8</java.version>
        <json.version>1.2.56</json.version>
        <mybatis-plus-boot-starter.version>3.2.0</mybatis-plus-boot-starter.version>
        <lombok.version>1.18.8</lombok.version>
        <commons-collection.version>3.2.2</commons-collection.version>
        <commons-lang3.version>3.8.1</commons-lang3.version>
        <jwt.version>0.9.1</jwt.version>
        <oauth-auto.version>2.0.6.RELEASE</oauth-auto.version>
        <thymeleaf-extras-data-attribute.version>3.0.4.RELEASE</thymeleaf-extras-data-attribute.version>
        <oauth2.version>2.3.6.RELEASE</oauth2.version>
        <springsecurity-jwt.version>1.0.7.RELEASE</springsecurity-jwt.version>
        <common-cite.version>1.0.1-SNAPSHOT</common-cite.version>
        <spring.boot.version>2.2.0.RELEASE</spring.boot.version>
        <mysql.version>8.0.18</mysql.version>
        <jedis.version>2.9.0</jedis.version>
        <poi.version>4.1.0</poi.version>
        <pdf.version>5.5.13</pdf.version>
        <org.json.version>20180813</org.json.version>
        <activiti.version>5.22.0</activiti.version>
        <spring.social.version>1.1.6.RELEASE</spring.social.version>
    </properties>


    <!--子子產品Spring Boot公共依賴-->
    <dependencies>
        <!--        springboot相關  begin-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>${spring.boot.version}</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>${spring.boot.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>redis.clients</groupId>
                    <artifactId>jedis</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>
        <!--        springboot相關  end-->
        <!--        redis start-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.1.0</version>
        </dependency>
        <!--        redis end-->
        <!-- mysql驅動  start-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
            <version>${mysql.version}</version>
        </dependency>
        <!-- mysql驅動  end-->
        <!--mybatis-plus begin-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus-boot-starter.version}</version>
        </dependency>
        <!--mybatis-plus end-->
        <!--spring-security-oauth2 begin-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>${spring.boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
            <version>${oauth-auto.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>${oauth2.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-jwt</artifactId>
            <version>${springsecurity-jwt.version}</version>
        </dependency>
        <!--spring-security-oauth2 end-->
        <!--        模闆引擎支援SpringSecurity  start-->
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity5</artifactId>
            <version>${thymeleaf-extras-data-attribute.version}</version>
        </dependency>
        <!--        模闆引擎支援SpringSecurity  end-->

        <!--        spring第三方支援 start-->
        <dependency>
            <groupId>org.springframework.social</groupId>
            <artifactId>spring-social-config</artifactId>
            <version>${spring.social.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.social</groupId>
            <artifactId>spring-social-core</artifactId>
            <version>${spring.social.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.social</groupId>
            <artifactId>spring-social-security</artifactId>
            <version>${spring.social.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.social</groupId>
            <artifactId>spring-social-web</artifactId>
            <version>${spring.social.version}</version>
        </dependency>
        <!--        spring第三方支援 end-->
        <!--        poi支援  start-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>${poi.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>${poi.version}</version>
        </dependency>
        <!--        poi支援  end-->

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.10</version>
        </dependency>

        <!--        json start-->
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>${org.json.version}</version>
        </dependency>
        <!--        json end-->
        <!--        pdf讀寫支援 start-->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>${pdf.version}</version>
        </dependency>
        <!--        pdf讀寫支援 end-->

        <!--        郵件支援 start-->
        <dependency>
            <groupId>com.sun.mail</groupId>
            <artifactId>javax.mail</artifactId>
            <version>1.6.2</version>
        </dependency>
        <!--        郵件支援 end-->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-tools</artifactId>
            <version>2.0</version>
        </dependency>

        <!--        activiti start-->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-engine</artifactId>
            <version>${activiti.version}</version>
            <exclusions>
                <exclusion>
                    <artifactId>mybatis</artifactId>
                    <groupId>org.mybatis</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-modeler</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-diagram-rest</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-process-validation</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-rest</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-json-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-image-generator</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-model</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.uuid</groupId>
            <artifactId>java-uuid-generator</artifactId>
            <version>3.1.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-codec</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-dom</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-xml</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-util</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-gvt</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-svggen</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-parser</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-transcoder</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-svg-dom</artifactId>
            <version>1.7</version>
        </dependency>
        <!--activiti end-->
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <classifier>exec</classifier>
                    <mainClass>com.zlx.bpms.BpmsPermissionWebApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                    <testFailureIgnore>true</testFailureIgnore>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
           

修改application.properties檔案,增加資料庫配置,mybatis-plus相關配置等資訊(關于mybatis-plus配置資訊如有不懂的,可以在GitHub上搜尋,為了友善也可以直接檢視我的項目代碼。)。啟動項目

控制台出現Using generated security password: 71a6581e-ce07-4a08-895b-17d11e24b0b0這樣一串日志,證明內建Security成功。

打開浏覽器,通路項目位址,會看到如下頁面:

Spring Boot Security 實作背景&amp;權限管理系統(一)
到這裡,也就是我們所做的一切都已經按照我們的預期順利進行,那麼由于時間有限,就先到這裡結束了。稍後我會一一進行更新。喜歡的小夥伴動動你們的小手,幫忙點點支援。