未验证 提交 daa2ac4f 编写于 作者: sinat_25235033's avatar sinat_25235033 提交者: GitHub

add support redis cache session sample (#88)

上级 5d030384
......@@ -17,5 +17,6 @@
<module>quarkus-sureness</module>
<module>spring-webflux-sureness</module>
<module>sureness-session</module>
<module>sureness-redis-session</module>
</modules>
</project>
\ No newline at end of file
<?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>sureness</artifactId>
<groupId>com.usthe.sureness</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sureness-redis-session</artifactId>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.usthe.sureness</groupId>
<artifactId>sureness-core</artifactId>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.4.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
{
"info": {
"_postman_id": "d85057b4-004a-4fc4-a9f2-7d791e826326",
"name": "sureness-sample-session",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "http://localhost:8088/api/v1/source1-basic auth",
"protocolProfileBehavior": {
"disableBodyPruning": true
},
"request": {
"auth": {
"type": "basic",
"basic": [
{
"key": "username",
"value": "tom",
"type": "string"
},
{
"key": "password",
"value": "32113",
"type": "string"
}
]
},
"method": "GET",
"header": [
{
"key": "Content-Type",
"name": "Content-Type",
"value": "application/json",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": ""
},
"url": {
"raw": "http://localhost:8088/api/v1/source1",
"protocol": "http",
"host": [
"localhost"
],
"port": "8088",
"path": [
"api",
"v1",
"source1"
]
}
},
"response": []
},
{
"name": "http://localhost:8088/api/v1/source1-basic auth",
"request": {
"auth": {
"type": "basic",
"basic": [
{
"key": "username",
"value": "tom",
"type": "string"
},
{
"key": "password",
"value": "32113",
"type": "string"
}
]
},
"method": "POST",
"header": [
{
"key": "Content-Type",
"name": "Content-Type",
"type": "text",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": ""
},
"url": {
"raw": "http://localhost:8088/api/v1/source1",
"protocol": "http",
"host": [
"localhost"
],
"port": "8088",
"path": [
"api",
"v1",
"source1"
]
}
},
"response": []
},
{
"name": "http://localhost:8088/api/v1/source1-basic auth",
"request": {
"auth": {
"type": "basic",
"basic": [
{
"key": "username",
"value": "tom",
"type": "string"
},
{
"key": "password",
"value": "32113",
"type": "string"
}
]
},
"method": "PUT",
"header": [
{
"key": "Content-Type",
"name": "Content-Type",
"type": "text",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": ""
},
"url": {
"raw": "http://localhost:8088/api/v1/source1",
"protocol": "http",
"host": [
"localhost"
],
"port": "8088",
"path": [
"api",
"v1",
"source1"
]
}
},
"response": []
},
{
"name": "http://localhost:8088/api/v1/source1-basic auth",
"request": {
"auth": {
"type": "basic",
"basic": [
{
"key": "username",
"value": "tom",
"type": "string"
},
{
"key": "password",
"value": "32113",
"type": "string"
}
]
},
"method": "DELETE",
"header": [
{
"key": "Content-Type",
"name": "Content-Type",
"type": "text",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": ""
},
"url": {
"raw": "http://localhost:8088/api/v1/source1",
"protocol": "http",
"host": [
"localhost"
],
"port": "8088",
"path": [
"api",
"v1",
"source1"
]
}
},
"response": []
},
{
"name": "http://localhost:8088/api/v1/source1-basic auth",
"request": {
"auth": {
"type": "basic",
"basic": [
{
"key": "username",
"value": "tom",
"type": "string"
},
{
"key": "password",
"value": "32113",
"type": "string"
}
]
},
"method": "PATCH",
"header": [
{
"key": "Content-Type",
"name": "Content-Type",
"type": "text",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": ""
},
"url": {
"raw": "http://localhost:8088/api/v1/source1",
"protocol": "http",
"host": [
"localhost"
],
"port": "8088",
"path": [
"api",
"v1",
"source1"
]
}
},
"response": []
}
],
"event": [
{
"listen": "prerequest",
"script": {
"type": "text/javascript",
"exec": [
""
]
}
},
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
""
]
}
}
]
}
\ No newline at end of file
package com.usthe.sureness.sample.redis.session;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
/**
* BOOT
* @author tomsun28
* @date 17:17 2019-05-12
*/
@SpringBootApplication
@ServletComponentScan
@EnableRedisHttpSession
public class RedisSessionApplication {
public static void main(String[] args) {
SpringApplication.run(RedisSessionApplication.class, args);
}
}
package com.usthe.sureness.sample.redis.session.controller;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* simulate api controller, for testing
* @author tomsun28
* @date 17:35 2019-05-12
*/
@RestController
public class SimulateController {
/** access success message **/
public static final String SUCCESS_ACCESS_RESOURCE = "access this resource: %s success";
@GetMapping("/api/v1/source1")
public ResponseEntity<Map<String, String>> api1Mock1(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@PostMapping("/api/v1/source1")
public ResponseEntity<Map<String, String>> api1Mock2(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@PutMapping("/api/v1/source1")
public ResponseEntity<Map<String, String>> api1Mock3(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@DeleteMapping("/api/v1/source1")
public ResponseEntity<Map<String, String>> api1Mock4(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@PatchMapping("/api/v1/source1")
public ResponseEntity<Map<String, String>> api1Mock5(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@GetMapping("/api/v1/source2/{var1}/{var2}")
public ResponseEntity<Map<String, String>> api1Mock6(HttpServletRequest request, @PathVariable String var1, @PathVariable Integer var2 ) {
Map<String, String> resultMap = new HashMap<>(3);
resultMap.putAll(getResponseMap(request));
if (!StringUtils.isEmpty(var1)) {
resultMap.put("var1", var1);
}
if (Objects.nonNull(var2)) {
resultMap.put("var2", String.valueOf(var2));
}
return ResponseEntity.ok(resultMap);
}
@PostMapping("/api/v1/source2/{var1}")
public ResponseEntity<Map<String, String>> api1Mock7(HttpServletRequest request, @PathVariable String var1) {
Map<String, String> resultMap = new HashMap<>(2);
resultMap.putAll(getResponseMap(request));
if (!StringUtils.isEmpty(var1)) {
resultMap.put("var1", var1);
}
return ResponseEntity.ok(resultMap);
}
@GetMapping("/api/v1/source2")
public ResponseEntity<Map<String, String>> api1Mock8(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@PatchMapping("/api/v1/source2")
public ResponseEntity<Map<String, String>> api1Mock10(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@GetMapping("/api/v1/source3")
public ResponseEntity<Map<String, String>> api1Mock11(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@PostMapping("/api/v1/source3")
public ResponseEntity<Map<String, String>> api1Mock12(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@PutMapping("/api/v1/source3")
public ResponseEntity<Map<String, String>> api1Mock13(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@DeleteMapping("/api/v1/source3")
public ResponseEntity<Map<String, String>> api1Mock14(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@GetMapping("/api/v2/source3/{var1}")
public ResponseEntity<Map<String, String>> api1Mock15(HttpServletRequest request, @PathVariable String var1) {
return ResponseEntity.ok(getResponseMap(request));
}
@GetMapping("/api/v2/source4")
public ResponseEntity<Map<String, String>> api2Mock16(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@PostMapping("/api/v2/source4")
public ResponseEntity<Map<String, String>> api2Mock17(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@PutMapping("/api/v2/source4")
public ResponseEntity<Map<String, String>> api2Mock18(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@DeleteMapping("/api/v2/source4")
public ResponseEntity<Map<String, String>> api2Mock19(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@PatchMapping("/api/v2/source4")
public ResponseEntity<Map<String, String>> api2Mock20(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@GetMapping("/api/v2/source5")
public ResponseEntity<Map<String, String>> api2Mock21(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@PostMapping("/api/v2/source5")
public ResponseEntity<Map<String, String>> api2Mock22(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@DeleteMapping("/api/v2/source5")
public ResponseEntity<Map<String, String>> api2Mock23(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@PutMapping("/api/v2/source5")
public ResponseEntity<Map<String, String>> api2Mock24(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@PatchMapping("/api/v2/source5")
public ResponseEntity<Map<String, String>> api2Mock25(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@GetMapping("/api/v2/source6")
public ResponseEntity<Map<String, String>> api2Mock26(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@PostMapping("/api/v2/source6")
public ResponseEntity<Map<String, String>> api2Mock27(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@DeleteMapping("/api/v2/source6")
public ResponseEntity<Map<String, String>> api2Mock28(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@PutMapping("/api/v2/source6")
public ResponseEntity<Map<String, String>> api2Mock29(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
@PatchMapping("/api/v2/source6")
public ResponseEntity<Map<String, String>> api2Mock30(HttpServletRequest request) {
return ResponseEntity.ok(getResponseMap(request));
}
/**
* get the response map data from request
* @param request http request
* @return map data
*/
private Map<String, String> getResponseMap(HttpServletRequest request) {
StringBuilder builder = new StringBuilder();
String requestUri = request.getRequestURI();
builder.append(requestUri);
builder.append("--");
String requestType = request.getMethod();
builder.append(requestType);
builder.append("--");
return Collections.singletonMap("result", String.format(SUCCESS_ACCESS_RESOURCE, builder.toString()));
}
}
package com.usthe.sureness.sample.redis.session.sureness;
import com.usthe.sureness.handler.AttachSessionServletHandler;
import com.usthe.sureness.handler.HandlerManager;
import com.usthe.sureness.matcher.DefaultPathRoleMatcher;
import com.usthe.sureness.matcher.PathTreeProvider;
import com.usthe.sureness.matcher.TreePathRoleMatcher;
import com.usthe.sureness.mgt.SurenessSecurityManager;
import com.usthe.sureness.processor.DefaultProcessorManager;
import com.usthe.sureness.processor.Processor;
import com.usthe.sureness.processor.ProcessorManager;
import com.usthe.sureness.processor.support.NoneProcessor;
import com.usthe.sureness.processor.support.PasswordProcessor;
import com.usthe.sureness.processor.support.SessionProcessor;
import com.usthe.sureness.provider.SurenessAccountProvider;
import com.usthe.sureness.provider.annotation.AnnotationPathTreeProvider;
import com.usthe.sureness.provider.ducument.DocumentAccountProvider;
import com.usthe.sureness.provider.ducument.DocumentPathTreeProvider;
import com.usthe.sureness.subject.SubjectFactory;
import com.usthe.sureness.subject.SurenessSubjectFactory;
import com.usthe.sureness.subject.creater.BasicSubjectServletCreator;
import com.usthe.sureness.subject.creater.NoneSubjectServletCreator;
import com.usthe.sureness.subject.creater.SessionSubjectServletCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* sureness config,Use DefaultSurenessConfig
* @author tomsun28
* @date 23:38 2019-05-12
*/
@Configuration
public class SurenessConfiguration {
@Bean
ProcessorManager processorManager() {
// process init
List<Processor> processorList = new LinkedList<>();
// use default none processor
NoneProcessor noneProcessor = new NoneProcessor();
processorList.add(noneProcessor);
// use default basic auth processor
PasswordProcessor passwordProcessor = new PasswordProcessor();
SurenessAccountProvider accountProvider = new DocumentAccountProvider();
passwordProcessor.setAccountProvider(accountProvider);
processorList.add(passwordProcessor);
// use session auth processor
SessionProcessor sessionProcessor = new SessionProcessor();
processorList.add(sessionProcessor);
return new DefaultProcessorManager(processorList);
}
@Bean
TreePathRoleMatcher pathRoleMatcher() {
// the path tree resource load from document - sureness.yml
PathTreeProvider documentPathTreeProvider = new DocumentPathTreeProvider();
// the path tree resource load form annotation - @RequiresRoles @WithoutAuth
AnnotationPathTreeProvider annotationPathTreeProvider = new AnnotationPathTreeProvider();
annotationPathTreeProvider.setScanPackages(Collections.singletonList("com.usthe.sureness.sample.tom.controller"));
// pathRoleMatcher init
DefaultPathRoleMatcher pathRoleMatcher = new DefaultPathRoleMatcher();
pathRoleMatcher.setPathTreeProviderList(Arrays.asList(
documentPathTreeProvider,
annotationPathTreeProvider));
pathRoleMatcher.buildTree();
return pathRoleMatcher;
}
@Bean
SubjectFactory subjectFactory() {
// SubjectFactory init
SubjectFactory subjectFactory = new SurenessSubjectFactory();
subjectFactory.registerSubjectCreator(Arrays.asList(
// attention! must add noSubjectCreator first
new NoneSubjectServletCreator(),
// use default session jwt subject creator
new SessionSubjectServletCreator(),
// use default basic auth subject creator
new BasicSubjectServletCreator()));
return subjectFactory;
}
@Bean
HandlerManager successHandlerManager() {
HandlerManager handlerManager = new HandlerManager();
handlerManager.registerHandler(new AttachSessionServletHandler());
return handlerManager;
}
@Bean
SurenessSecurityManager securityManager(ProcessorManager processorManager,
TreePathRoleMatcher pathRoleMatcher,
SubjectFactory subjectFactory,
HandlerManager handlerManager) {
// surenessSecurityManager init
SurenessSecurityManager securityManager = SurenessSecurityManager.getInstance();
securityManager.setPathRoleMatcher(pathRoleMatcher);
securityManager.setSubjectFactory(subjectFactory);
securityManager.setProcessorManager(processorManager);
securityManager.setHandlerManager(handlerManager);
return securityManager;
}
}
package com.usthe.sureness.sample.redis.session.sureness;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.usthe.sureness.mgt.SurenessSecurityManager;
import com.usthe.sureness.processor.exception.*;
import com.usthe.sureness.subject.SubjectSum;
import com.usthe.sureness.util.SurenessContextHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* sureness filter class example, filter all http request
* @author tomsun28
* @date 17:22 2019-05-12
*/
@Order(1)
@WebFilter(filterName = "SurenessFilterExample", urlPatterns = "/*", asyncSupported = true)
public class SurenessFilterExample implements Filter {
/** logger **/
private static final Logger logger = LoggerFactory.getLogger(SurenessFilterExample.class);
private static final String UPGRADE = "Upgrade";
private static final String WEBSOCKET = "websocket";
@Override
public void init(FilterConfig filterConfig) {
logger.info("surenessFilter initialized");
}
@Override
public void destroy() {
logger.info("surenessFilter destroyed");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
try {
SubjectSum subject = SurenessSecurityManager.getInstance().checkIn(servletRequest);
// You can consider using SurenessContextHolder to bind subject in threadLocal
// if bind, please remove it when end
if (subject != null) {
SurenessContextHolder.bindSubject(subject);
}
} catch (ProcessorNotFoundException | UnknownAccountException | UnsupportedSubjectException e4) {
logger.debug("this request is illegal");
responseWrite(ResponseEntity
.status(HttpStatus.BAD_REQUEST).body(e4.getMessage()), servletResponse);
return;
} catch (DisabledAccountException | ExcessiveAttemptsException e2 ) {
logger.debug("the account is disabled");
responseWrite(ResponseEntity
.status(HttpStatus.UNAUTHORIZED).body(e2.getMessage()), servletResponse);
return;
} catch (IncorrectCredentialsException | ExpiredCredentialsException e3) {
logger.debug("this account credential is incorrect or expired");
responseWrite(ResponseEntity
.status(HttpStatus.UNAUTHORIZED).body(e3.getMessage()), servletResponse);
return;
} catch (NeedDigestInfoException e5) {
logger.debug("you should try once again with digest auth information");
responseWrite(ResponseEntity
.status(HttpStatus.UNAUTHORIZED)
.header("WWW-Authenticate", e5.getAuthenticate()).build(), servletResponse);
return;
} catch (UnauthorizedException e6) {
logger.debug("this account can not access this resource");
responseWrite(ResponseEntity
.status(HttpStatus.FORBIDDEN).body(e6.getMessage()), servletResponse);
return;
} catch (RuntimeException e) {
logger.error("other exception happen: ", e);
responseWrite(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(),
servletResponse);
return;
}
try {
// if ok, doFilter and add subject in request
filterChain.doFilter(servletRequest, servletResponse);
} finally {
int statusCode = ((HttpServletResponse) servletResponse).getStatus();
String upgrade = ((HttpServletResponse) servletResponse).getHeader(UPGRADE);
if (statusCode != HttpStatus.SWITCHING_PROTOCOLS.value() || !WEBSOCKET.equals(upgrade)) {
SurenessContextHolder.clear();
}
}
}
/**
* write response json data
* @param content content
* @param response response
*/
private static void responseWrite(ResponseEntity content, ServletResponse response) {
response.setCharacterEncoding("UTF-8");
((HttpServletResponse)response).setStatus(content.getStatusCodeValue());
content.getHeaders().forEach((key, value) ->
((HttpServletResponse) response).addHeader(key, value.get(0)));
try (PrintWriter printWriter = response.getWriter()) {
if (content.getBody() != null) {
if (content.getBody() instanceof String) {
printWriter.write(content.getBody().toString());
} else {
ObjectMapper objectMapper = new ObjectMapper();
printWriter.write(objectMapper.writeValueAsString(content.getBody()));
}
} else {
printWriter.flush();
}
} catch (IOException e) {
logger.error("responseWrite response error: ", e);
}
}
}
server:
port: 8088
spring:
profiles:
active: dev
redis:
host: 47.110.55.246
port: 6368
logging:
level:
root: info
\ No newline at end of file
## -- sureness.yml document dataSource-- ##
# load api resource which need be protected, config role who can access these resource.
# resources that are not configured are also authenticated and protected by default, but not authorized
# eg: /api/v2/host===post===[role2,role3,role4] means /api/v2/host===post can be access by role2,role3,role4
# eg: /api/v1/getSource3===get===[] means /api/v1/getSource3===get can not be access by any role
resourceRole:
- /api/v2/host===post===[role2,role3,role4]
- /api/v2/host===get===[role2,role3,role4]
- /api/v2/host===delete===[role2,role3,role4]
- /api/v2/host===put===[role2,role3,role4]
- /api/mi/**===put===[role2,role3,role4]
- /api/v1/getSource1===get===[role1,role2]
- /api/v2/getSource2/*/*===get===[role2]
- /api/v1/source1===get===[role2]
- /api/v1/source1===post===[role1]
- /api/v1/source1===delete===[role3]
- /api/v1/source1===put===[role1,role2]
- /api/v1/source2===get===[]
- /api/v1/source2/*/*===get===[role2]
- /api/v2/source3/*===get===[role2]
- /webSocket/demo===get===[role1]
- /api/v3/source===*===[role2]
# load api resource which do not need be protected, means them need be excluded.
# these api resource can be access by everyone
excludedResource:
- /api/v1/source3===get
- /api/v3/host===get
- /api/v3/book===get
- /api/v1/account/auth===post
- /**/*.html===get
- /**/*.js===get
- /**/*.css===get
- /**/*.ico===get
- /**/*.ttf===get
- /**/*.png===get
- /**/*.gif===get
- /swagger-resources/**===get
- /v2/api-docs===get
- /**/*.png===*
# account info
# there are three account: admin, root, tom
# eg: admin has [role1,role2] ROLE, unencrypted password is admin, encrypted password is 0192023A7BBD73250516F069DF18B500
# eg: root has role1, unencrypted password is 23456
# eg: tom has role3, unencrypted password is 32113
account:
- appId: admin
# if add salt, the password is encrypted password - the result: MD5(password+salt)
# if no salt, the password is unencrypted password
credential: 0192023A7BBD73250516F069DF18B500
salt: 123
role: [role1,role2]
- appId: root
credential: 23456
role: [role1]
- appId: tom
credential: 32113
role: [role3]
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册