從零開始SpringCloud Alibaba電商系統(十)——基於Redis Session的認證鑑權

零、系列

歡迎來嫖從零開始SpringCloud Alibaba電商系列:

  1. 從零開始SpringCloud Alibaba電商系統(一)——Alibaba與Nacos服務註冊與發現
  2. 從零開始SpringCloud Alibaba電商系統(二)——Nacos配置中心
  3. 從零開始SpringCloud Alibaba電商系統(三)——Sentinel流量防衛兵介紹、流量控制demo
  4. 從零開始SpringCloud Alibaba電商系統(四)——Sentinel的fallback和blockHandler
  5. 從零開始SpringCloud Alibaba電商系統(五)——Feign Demo,Sentinel+Feign實現多節點間熔斷/服務降級
  6. 從零開始SpringCloud Alibaba電商系統(六)——Sentinel規則持久化到Nacos配置中心
  7. 從零開始SpringCloud Alibaba電商系統(七)——Spring Security實現登錄認證、權限控制
  8. 從零開始SpringCloud Alibaba電商系統(八)——用一個好看的Swagger接口文檔
  9. 從零開始SpringCloud Alibaba電商系統(九)——基於Spring Security OAuth2實現SSO-認證服務器(非JWT)

一、 概述

 前文我們考慮了OAuth2的鑑權方式,但是作爲B2C電商系統來說,它的功能有些超出需求範圍。

OAuth2的目的是認證中心要不要給服務提供者授權。

 而我們當前權限設計所需要的是:

能讓多子系統共享用戶狀態,擁有相同的鑑權模式。

基於以上考慮,本文將嘗試採用redis做session保存用戶信息,在各個子服務系統複用相同的認證鑑權,並依然借用spring security的權限控制功能,基本的系統角色有如下三種:
在這裏插入圖片描述
基本登錄流程如下:
在這裏插入圖片描述
當然,我們還需要考慮角色對資源的權限,通過spring security來實現接口的訪問限制,通過用戶-角色-資源等庫表來實現資源粒度,表結構如下:
在這裏插入圖片描述
基本瞭解了概念,接下來我們就從spring security配置redis session開始,實現一個可用的權限認證功能。

二、如何整合Redis做Session

有一些方式可以選擇:
  1. spring security原本是使用concurrentHashMap來做session的,我們只需要將session的相關實現類替換成redis爲數據存儲結構 。SessionRegistryImpl是我們需要覆蓋重寫的類,然後再spring security配置時將我們的實現類註冊進去。
  2. 直接使用Spring-Session-Redis,樂樂十分推薦第二種方式,畢竟都是自己做的框架,用起來就是兩個字——絲滑。

三、準備環境

Redis Server 一臺。
本地代碼 一堆:樂樂這裏用的是父子項目。

 mall是最外層父模塊。
 common爲所有子系統的依賴模塊,認證邏輯會寫在這裏,這個模塊不會作爲微服務中的一個來單獨部署,下面只是爲了方便演示。
 user爲一個子系統模塊,依賴common。
 暫時就用一個common,一個user來演示兩個客戶端。

四、實現流程

數據庫表放在了flywaydb文件中,會隨項目啓動自行創建到數據庫中。其他相關的配置文件不再贅述,有需要的同學可以直接去底部拿demo。

common模塊

主要的認證邏輯集中在common模塊,然後其他子系統都會引用common的代碼。

  1. 使用上述表結構,實現我們的自定義UserDetails,這裏的mapper由逆向工程實現。
    具體的sql和代碼放在最下方demo中。
  2. 爲父子模塊配置依賴,如果在自己項目中,已經有security的話可以只引入spring-session-redis。
 <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
  </dependency>
  1. 配置文件,application.properties的內容主要是redis相關(在spring security配置健全的前提下),其中redis.xxx的配置爲筆者自定義。
redis.host=localhost
redis.port=6379
session.redis.timeout=60000
spring.session.store-type=redis
server.servlet.session.timeout=120
spring.session.redis.flush-mode=on-save
spring.session.redis.namespace=spring:session
  1. 配置Redis的相關Bean,需要一個Java客戶端,這裏使用Lettuce。
    這裏使用的redis.XXX就是前一步配置文件中配置的
@Configuration
public class RedisConfig  {

    @Value("${redis.host}")
    private String redisServer;
    @Value("${redis.port}")
    private Integer redisPort;
    @Value("${redis.password}")
    private String redisPassword;

    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(redisServer, redisPort);
        redisStandaloneConfiguration.setPassword(redisPassword);

        return new LettuceConnectionFactory(redisStandaloneConfiguration);
    }
}

  1. 使用RBAC數據庫結構實現UserDetails。
    筆者這裏使用了easycode+mybatisplus逆向生成了這些表的代碼,不想折騰的同學可以直達底部。
    唯一個人寫的就是MPermissionDao.selectPermissionByUserId方法,用來查詢該用戶所擁有的所有資源權限。
    在這裏插入圖片描述

  2. 這裏只是在user表插入了一條用戶名密碼都爲root的數據,用來進行redis session的流程,當然密碼需要加密,筆者在單元測試方法寫了一些插入數據時加密密碼的測試方法,可以參考
    在這裏插入圖片描述

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {

    @Autowired
    private MUserDao mUserDao;
	// Bean來自WebSecurityConfiguration
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Test
    public void testInsert(){
        MUser user = MUser.builder().username("root").password(bCryptPasswordEncoder.encode("root")).build();
        mUserDao.insert(user);
    }
}

到此爲止,common模塊已經可以測試使用了,單模塊測試,我們跑一下。
7. 啓動common的application,root/root登錄。
在這裏插入圖片描述
在這裏插入圖片描述

查看我們的redis庫是否有了session數據,成功!內容我們就不分析了,名字敘述的很清晰。

在這裏插入圖片描述

User模塊

  1. 新建user子模塊之前,需要對common模塊做一個小小的改動,那就是增加spring.factories,否則啓動user模塊時,common模塊的配置類是不會被加載的。
    在這裏插入圖片描述

  2. 新建user模塊,直接新建一個springboot項目即可,將parent改爲mall。然後依賴只需要添加common,這個字數比較少直接貼上來。

<?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">
    <parent>
        <artifactId>mall</artifactId>
        <groupId>org.lele</groupId>
        <version>0.1</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>
    <artifactId>user</artifactId>

    <dependencies>
    <dependency>
        <groupId>org.lele</groupId>
        <artifactId>common</artifactId>
        <version>0.1</version>
    </dependency>
</dependencies>
</project>

在這裏插入圖片描述

  1. 按照common的配置,配置一份user的,在本節demo中,需要修改的有服務名、服務端口、flywaydb的名稱(不用也可以不改)。
    不想使用nacos配置中心的同學可以直接看下面貼的這一坨
spring.application.name=user
server.port=8083
spring.cloud.nacos.discovery.server-addr=localhost:8848
management.endpoints.web.exposure.include=*
#spring.cloud.sentinel.enabled=false
#spring.cloud.sentinel.transport.port=8121
#spring.cloud.sentinel.transport.dashboard=localhost:8080
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url= jdbc:mysql://localhost:3306/mall_user?useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
spring.datasource.username= root
spring.datasource.password= root
spring.datasource.druid.initial-size= 5
spring.datasource.druid.max-active=5
spring.datasource.druid.max-wait=10000
# flyway enable
spring.flyway.enabled=true
spring.flyway.baseline-on-migrate=true
spring.flyway.locations=classpath:db/migration
spring.flyway.table=common_version
spring.flyway.baseline-version=0
spring.flyway.encoding=UTF-8
spring.flyway.validate-on-migrate=false
spring.flyway.placeholder-prefix=##(
spring.flyway.placeholder-suffix=)
#mybatis-plus
mybatis-plus.mapper-locations= classpath:/mapper/**.xml
#redis
redis.host=localhost
redis.port=6379
redis.password=redisPassword
session.redis.timeout=60000
spring.session.store-type=redis
server.servlet.session.timeout=120
spring.session.redis.flush-mode=on-save
spring.session.redis.namespace=spring:session
  1. user模塊配置完畢,啓動application。
    訪問 localhost:8083
    在這裏插入圖片描述
    可以不用登陸直接訪問到user模塊的服務,這是因爲之前common也就是8082服務已經將seesion註冊到redis中了。當然,換一個(或重啓)瀏覽器肯定還是要重新登錄的。

五、demo

至此,spring security配置完畢,權限系統也可以直接使用了,數據可以自己添加,最好是配合一個後端管理系統來管理資源權限,當然這個樂樂(筆者)之後也會慢慢做出來的。
https://github.com/flyChineseBoy/lel-mall/tree/master/mall10

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