Core Module: shenyu-plugin-sign
Core Class: org.apache.shenyu.plugin.sign.SignPlugin
sign
dependency in the pom.xml
file of the gateway<!-- apache shenyu sign plugin start--> <dependency> <groupId>org.apache.shenyu</groupId> <artifactId>shenyu-spring-boot-starter-plugin-sign</artifactId> <version>${project.version}</version> </dependency> <!-- apache shenyu sign plugin end-->
shenyu-admin
--> BasicConfig --> Plugin --> sign
set to enable.AK/SK
and use it with the Sign
plugin to achieve precise authority control based on URI level.First, we can add a piece of authentication information in BasicConfig
- Authentication
Then configure this authentication information
appParam
./order/**
.After submit, a piece of authentication information is generated, which contains AppKey
and AppSecret
, which is the AK/SK
in the Sign
plugin.
Please refer to the detailed instructions of the Sign
plugin: Sign Plugin.
For the created authentication information, you can click PathOperation
at the end of a piece of authentication information.
>
or <
in the middle to move the checked data to the corresponding list.AK/SK
authentication technical scheme.Step 1: AK/SK
is assigned by the gateway. For example, the AK
assigned to you is: 1TEST123456781
SK is: ` 506eeb535cf740d7a755cb49f4a1536'
Step 2: Decide the gateway path you want to access, such as /api/service/abc
Step 3: Construct parameters (the following are general parameters)
Field | Value | Description |
---|---|---|
timestamp | current timestamp(String) | The number of milliseconds of the current time(gateway will filter requests the before 5 minutes) |
path | /api/service/abc | The path that you want to request(Modify by yourself according to your configuration of gateway) |
version | 1.0.0 | 1.0.0 is a fixed string value |
Sort the above three field natually according to the key, then splice fields and fields, finally splice SK. The following is a code example.
Step 1: First, construct a Map.
Map<String, String> map = Maps.newHashMapWithExpectedSize(3); //timestamp is string format of millisecond. String.valueOf(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli()) map.put("timestamp","1571711067186"); // Value should be string format of milliseconds map.put("path", "/api/service/abc"); map.put("version", "1.0.0");
Step 2: Sort the Keys
naturally, then splice the key and values, and finally splice the SK
assigned to you.
List<String> storedKeys = Arrays.stream(map.keySet() .toArray(new String[]{})) .sorted(Comparator.naturalOrder()) .collect(Collectors.toList()); final String sign = storedKeys.stream() .map(key -> String.join("", key, params.get(key))) .collect(Collectors.joining()).trim() .concat("506EEB535CF740D7A755CB4B9F4A1536");
path/api/service/abctimestamp1571711067186version1.0.0506EEB535CF740D7A755CB4B9F4A1536
Step 3: Md5 encryption and then capitalization.
DigestUtils.md5DigestAsHex(sign.getBytes()).toUpperCase()
A021BF82BE342668B78CD9ADE593D683
.Step 1: First, construct a Map, and the map must save every request body parameters
Map<String, String> map = Maps.newHashMapWithExpectedSize(3); //timestamp is string format of millisecond. String.valueOf(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli()) map.put("timestamp","1660659201000"); // Value should be string format of milliseconds map.put("path", "/http/order/save"); map.put("version", "1.0.0"); // if your request body is:{"id":123,"name":"order"} map.put("id", "1"); map.put("name", "order")
Step 2: Sort the Keys
naturally, then splice the key and values, and finally splice the SK
assigned to you.
List<String> storedKeys = Arrays.stream(map.keySet() .toArray(new String[]{})) .sorted(Comparator.naturalOrder()) .collect(Collectors.toList()); final String sign = storedKeys.stream() .map(key -> String.join("", key, params.get(key))) .collect(Collectors.joining()).trim() .concat("2D47C325AE5B4A4C926C23FD4395C719");
id123nameorderpath/http/order/savetimestamp1660659201000version1.0.02D47C325AE5B4A4C926C23FD4395C719
Step 3: Md5 encryption and then capitalization.
DigestUtils.md5DigestAsHex(sign.getBytes()).toUpperCase()
35FE61C21F73E9AAFC46954C14F299D7
.If your visited path is:/api/service/abc
.
Address: http: domain name of gateway /api/service/abc
.
Set header
,header
Parameter:
Field | Value | Description |
---|---|---|
timestamp | 1571711067186 | Timestamp when signing |
appKey | 1TEST123456781 | The AK value assigned to you |
sign | A90E66763793BDBC817CF3B52AAAC041 | The signature obtained above |
version | 1.0.0 | 1.0.0 is a fixed value. |
The signature plugin will filter requests before 5
minutes by default
If the authentication fails, will return code 401
, message may change.
{ "code": 401, "message": "sign is not pass,Please check you sign algorithm!", "data": null }
Only those matched requests can be authenticated by signature.
Selectors and rules, please refer to: Selector And Rule Config
Authentication Guide
,public class Test1 { public static void main(String[] args) { Map<String, String> map = Maps.newHashMapWithExpectedSize(3); //timestamp为毫秒数的字符串形式 String.valueOf(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli()) map.put("timestamp","1660658725000"); //值应该为毫秒数的字符串形式 map.put("path", "/http/order/save"); map.put("version", "1.0.0"); map.put("id", "123"); map.put("name", "order"); // map.put("body", "{\"id\":123,\"name\":\"order\"}"); List<String> storedKeys = Arrays.stream(map.keySet() .toArray(new String[]{})) .sorted(Comparator.naturalOrder()) .collect(Collectors.toList()); final String sign = storedKeys.stream() .map(key -> String.join("", key, map.get(key))) .collect(Collectors.joining()).trim() .concat("2D47C325AE5B4A4C926C23FD4395C719"); System.out.println(sign); System.out.println(DigestUtils.md5DigestAsHex(sign.getBytes()).toUpperCase()); } }
path/http/order/savetimestamp1571711067186version1.0.02D47C325AE5B4A4C926C23FD4395C719
9696D3E549A6AEBE763CCC2C7952DDC1
public class Test2 { public static void main(String[] args) { Map<String, String> map = Maps.newHashMapWithExpectedSize(3); //timestamp为毫秒数的字符串形式 String.valueOf(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli()) map.put("timestamp","1660659201000"); //值应该为毫秒数的字符串形式 map.put("path", "/http/order/save"); map.put("version", "1.0.0"); List<String> storedKeys = Arrays.stream(map.keySet() .toArray(new String[]{})) .sorted(Comparator.naturalOrder()) .collect(Collectors.toList()); final String sign = storedKeys.stream() .map(key -> String.join("", key, map.get(key))) .collect(Collectors.joining()).trim() .concat("2D47C325AE5B4A4C926C23FD4395C719"); System.out.println(sign); System.out.println(DigestUtils.md5DigestAsHex(sign.getBytes()).toUpperCase()); } }
*signature with body:id123nameorderpath/http/order/savetimestamp1660659201000version1.0.02D47C325AE5B4A4C926C23FD4395C719
*sign with body result is:35FE61C21F73E9AAFC46954C14F299D7
shenyu-admin
--> BasicConfig --> Plugin --> sign
set to disabled.