1. 內(nèi)容說明
本文旨在使用開源輕量級(jí) Java 權(quán)限認(rèn)證框架sa-token+springcloud-gateway實(shí)現(xiàn)微服務(wù)在網(wǎng)關(guān)處統(tǒng)一鑒權(quán)。sa-token參考地址:https://sa-token.cc/doc.html#/
項(xiàng)目按照業(yè)務(wù)分為三個(gè)板塊,如圖:
- api(也就是微服務(wù)中各種api接口,不涉及任何權(quán)限相關(guān)代碼,只提供服務(wù))
- auth(認(rèn)證中心,實(shí)現(xiàn)登陸邏輯)
- gateway(網(wǎng)關(guān),實(shí)現(xiàn)轉(zhuǎn)發(fā)等,主要是統(tǒng)一鑒權(quán))
2. 項(xiàng)目實(shí)現(xiàn)
首先在idea創(chuàng)建一個(gè)項(xiàng)目mirco,然后在項(xiàng)目下依次創(chuàng)建三個(gè)module,這就不展開說了。接下來各模塊填充內(nèi)容。
2.1. auth模塊
2.1.1. pom.xml依賴
主要是web、satoken、satoken整合redis:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.3.5.RELEASE</version>
</dependency>
<!-- Sa-Token 權(quán)限認(rèn)證,在線文檔:https://sa-token.cc -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.34.0</version>
</dependency>
<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis-jackson</artifactId>
<version>1.34.0</version>
</dependency>
<!-- 提供Redis連接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
</dependencies>
2.1.2. controller類
提供登陸接口,實(shí)現(xiàn)登陸并返回登陸成功的token給前端:
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AuthController {
@GetMapping("/auth/doLogin")
public SaResult doLogin(String username, String password) {
// 此處僅作模擬示例,真實(shí)項(xiàng)目需要從數(shù)據(jù)庫中查詢數(shù)據(jù)進(jìn)行比對(duì)
if ("admin".equals(username) && "123456".equals(password)) {
StpUtil.login(10001);
} else if ("super".equals(username) && "123456".equals(password)) {
StpUtil.login(10002);
}else {
return SaResult.error("登錄失敗");
}
// 第3步,返回給前端
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
return SaResult.ok("登錄成功").setData(tokenInfo);
}
}
2.1.3. 啟動(dòng)類
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AuthApplication {
public static void main(String[] args) {
SpringApplication.run(AuthApplication.class, args);
}
}
2.1.4. application.yml配置文件
server:
port: 8082
spring:
# redis配置
redis:
# Redis數(shù)據(jù)庫索引(默認(rèn)為0)
database: 1
# Redis服務(wù)器地址
host: 127.0.0.1
# Redis服務(wù)器連接端口
port: 6379
# Redis服務(wù)器連接密碼(默認(rèn)為空)
# password:
# 連接超時(shí)時(shí)間
timeout: 10s
lettuce:
pool:
# 連接池最大連接數(shù)
max-active: 200
# 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒有限制)
max-wait: -1ms
# 連接池中的最大空閑連接
max-idle: 10
# 連接池中的最小空閑連接
min-idle: 0
2.2. gateway模塊
2.2.1. pom.xml依賴
主要是gateway、satoken、satoken整合redis:
<dependencies>
<!-- springCloud gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
<!-- httpClient依賴,缺少此依賴api網(wǎng)關(guān)轉(zhuǎn)發(fā)請(qǐng)求時(shí)可能發(fā)生503錯(cuò)誤 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-reactor-spring-boot-starter</artifactId>
<version>1.34.0</version>
</dependency>
<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis-jackson</artifactId>
<version>1.34.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
</dependencies>
2.2.2. 全局過濾器
主要是配置路由進(jìn)行攔截鑒權(quán),這里是整個(gè)鑒權(quán)的核心,具體的路由配置規(guī)則參考sa-token官網(wǎng):
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* [Sa-Token 權(quán)限認(rèn)證] 配置類
*/
@Configuration
public class SaTokenConfigure {
// 注冊(cè) Sa-Token全局過濾器
@Bean
public SaReactorFilter getSaReactorFilter() {
return new SaReactorFilter()
// 攔截地址
.addInclude("/**") /* 攔截全部path */
// 開放地址
.addExclude("/favicon.ico")
// 鑒權(quán)方法:每次訪問進(jìn)入
.setAuth(obj -> {
// 登錄校驗(yàn) -- 攔截所有路由,并排除/user/doLogin 用于開放登錄
SaRouter.match("/**", "/auth/doLogin", r -> StpUtil.checkLogin());
// 權(quán)限認(rèn)證 -- 不同模塊, 校驗(yàn)不同權(quán)限
SaRouter.match("/api/test1", r -> StpUtil.checkPermission("api.test1"));
SaRouter.match("/api/test2", r -> StpUtil.checkPermission("api.test2"));
SaRouter.match("/api/test3", r -> StpUtil.checkRoleOr("admin", "super"));
// 更多匹配 ... */
})
// 異常處理方法:每次setAuth函數(shù)出現(xiàn)異常時(shí)進(jìn)入
.setError(e -> {
return SaResult.error(e.getMessage());
})
;
}
}
2.2.3. 自定義權(quán)限接口
主要是定義用戶擁有的權(quán)限和角色,我這里直接寫死的,實(shí)際項(xiàng)目中通常應(yīng)該是auth認(rèn)證模塊登陸后從數(shù)據(jù)庫查出用戶的角色權(quán)限緩存到redis,然后這里再從redis取出來。
import cn.dev33.satoken.stp.StpInterface;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* 自定義權(quán)限驗(yàn)證接口擴(kuò)展,在需要鑒權(quán)時(shí)自動(dòng)調(diào)用
*/
@Component
public class StpInterfaceImpl implements StpInterface {
/**
* 返回一個(gè)賬號(hào)所擁有的權(quán)限碼集合
*/
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
// 本list僅做模擬,實(shí)際項(xiàng)目中要根據(jù)具體業(yè)務(wù)邏輯來查詢權(quán)限
List<String> list = new ArrayList<>();
if (Integer.parseInt(loginId.toString()) == 10001) {
list.add("api.test1");
} else if (Integer.parseInt(loginId.toString()) == 10002) {
list.add("api.test2");
}
return list;
}
/**
* 返回一個(gè)賬號(hào)所擁有的角色標(biāo)識(shí)集合 (權(quán)限與角色可分開校驗(yàn))
*/
@Override
public List<String> getRoleList(Object loginId, String loginType) {
// 本list僅做模擬,實(shí)際項(xiàng)目中要根據(jù)具體業(yè)務(wù)邏輯來查詢角色
List<String> list = new ArrayList<>();
if (Integer.parseInt(loginId.toString()) == 10001) {
list.add("admin");
} else if (Integer.parseInt(loginId.toString()) == 10002) {
list.add("super");
}
return list;
}
}
2.2.4. 啟動(dòng)類
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
2.2.5. application.yml配置文件
server:
port: 8083
spring:
application:
name: gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: api
uri: http://127.0.0.1:8081
predicates:
- Path=/api/**
- id: auth
uri: http://127.0.0.1:8082
predicates:
- Path=/auth/**
redis:
# Redis數(shù)據(jù)庫索引(默認(rèn)為0)
database: 1
# Redis服務(wù)器地址
host: 127.0.0.1
# Redis服務(wù)器連接端口
port: 6379
# Redis服務(wù)器連接密碼(默認(rèn)為空)
# password:
# 連接超時(shí)時(shí)間
timeout: 10s
lettuce:
pool:
# 連接池最大連接數(shù)
max-active: 200
# 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒有限制)
max-wait: -1ms
# 連接池中的最大空閑連接
max-idle: 10
# 連接池中的最小空閑連接
min-idle: 0
2.3. auth模塊
2.3.1. pom.xml依賴
主要是web:
<dependencies>
<!-- SpringBoot Web模塊 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
2.3.2. controller類
提供一些接口,用來驗(yàn)證satoken權(quán)限:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/api/test1")
public String test1() {
return "訪問成功--只有《api.test1》權(quán)限的才能訪問";
}
@GetMapping("/api/test2")
public String test2() {
return "訪問成功--只有《api.test2》權(quán)限的才能訪問";
}
@GetMapping("/api/test3")
public String test3() {
return "訪問成功--擁有《admin或者super角色》可以訪問";
}
@GetMapping("/api/test4")
public String test4() {
return "訪問成功--無需權(quán)限,登陸即可訪問";
}
}
2.3.3. 啟動(dòng)類
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ApiApplication {
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
}
2.3.4. application.yml配置文件
server:
port: 8081
3. 項(xiàng)目測試
-
首先通過網(wǎng)關(guān)登陸:http://localhost:8083/auth/doLogin?username=admin&password=123456
如圖正確的賬戶密碼登陸成功返回token,這里登陸的admin用戶。 -
不帶token訪問,訪問失?。篽ttp://localhost:8083/api/test1
-
攜帶token訪問,訪問成功:http://localhost:8083/api/test1
-
訪問無權(quán)限的接口失?。篽ttp://localhost:8083/api/test2
文章來源:http://www.zghlxwxcb.cn/news/detail-693488.html
- 訪問有角色權(quán)限的接口成功:http://localhost:8083/api/test3
4. 項(xiàng)目總結(jié)
至此,我們完成了gateway處統(tǒng)一使用sa-token鑒權(quán)。以上只是最基礎(chǔ)的網(wǎng)關(guān)統(tǒng)一鑒權(quán)的使用,更深層的比如內(nèi)外網(wǎng)隔離等請(qǐng)自行參考sa-token官網(wǎng)。個(gè)人覺得sa-token相當(dāng)牛逼,十分容易上手,不管你是單體、前后端分離還是微服務(wù)項(xiàng)目,都能輕松集成。相比于springsecurity學(xué)習(xí)成本降低很多。
另外本博客涉及的代碼已全部包含在文章里了,就不另外貼了。文章來源地址http://www.zghlxwxcb.cn/news/detail-693488.html
到了這里,關(guān)于【實(shí)現(xiàn)微服務(wù)集成satoken在網(wǎng)關(guān)gateway處統(tǒng)一鑒權(quán)】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!