Skip to content

Commit

Permalink
Support for URI role mapping rewriting
Browse files Browse the repository at this point in the history
  • Loading branch information
gudaoxuri committed Aug 26, 2019
1 parent 3e2f239 commit 2d93f01
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 23 deletions.
4 changes: 2 additions & 2 deletions docs/src/main/asciidoc/_chapter/framework/configuration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ dew: # Dew 参数key前缀
black-uri: # URL黑名单,支持ant风格
<Http Method>: [<URLs>] # URL黑名单列表,Method = all 表示所有方法
role-auth: # 角色认证
<Role Code>: # 角色编码
<Http Method>: [<URLs>] # 只有该角色才能访问的URL,支持ant风格,Method = all 表示所有方法
<Role Code>: # 角色编码,角色可以带租户,使用.分隔,e.g. tenant1.admin / tenant2.admin
<Http Method>: [<URLs>] # 只有该角色才能访问的URL,支持ant风格,支持继承与重写,Method = all 表示所有方法
token-kinds: # Token类型,可为不同的Token类型设置不同的过期时间、保留的版本
<Kind>: # Token类型名称,比如 PC/Android/... ,默认会创建名为 DEFAULT 的类型
expire-sec: 86400 # Token 过期时间(秒)
Expand Down
4 changes: 2 additions & 2 deletions docs/src/main/asciidoc/_chapter/framework/user-manual.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -788,8 +788,8 @@ dew:
black-uri: # URL黑名单,支持ant风格
<Http Method>: [<URLs>] # URL黑名单列表,Method = all 表示所有方法
role-auth: # 角色认证
<Role Code>: # 角色编码
<Http Method>: [<URLs>] # 只有该角色才能访问的URL,支持ant风格,Method = all 表示所有方法
<Role Code>: # 角色编码,角色可以带租户,使用.分隔,e.g. tenant1.admin / tenant2.admin
<Http Method>: [<URLs>] # 只有该角色才能访问的URL,支持ant风格,支持继承与重写,Method = all 表示所有方法
token-kinds: # Token类型,可为不同的Token类型设置不同的过期时间、保留的版本
<Kind>: # Token类型名称,比如 PC/Android/... ,默认会创建名为 DEFAULT 的类型
expire-sec: 86400 # Token 过期时间(秒)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class BasicHandlerInterceptor extends HandlerInterceptorAdapter {
private static final Logger logger = LoggerFactory.getLogger(BasicHandlerInterceptor.class);

private static final String URL_SPLIT = "@";
private static final String ROLE_SPLIT = ".";

private AntPathMatcher pathMatcher = new AntPathMatcher();

Expand Down Expand Up @@ -134,24 +135,37 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons
request.getMethod(), request.getRequestURI()), AuthException.class.getName());
return false;
}

// 角色权限处理
if (!roleAuth.isEmpty()) {
Set<String> needRoles = roleAuth.entrySet().stream()
.filter(entry -> pathMatcher.match(entry.getKey(), reqUri))
.flatMap(entry -> entry.getValue().stream())
.collect(Collectors.toSet());
if (!needRoles.isEmpty() && (StringUtils.isEmpty(token) || Dew.auth.getOptInfo(token)
.map(opt ->
((Set<OptInfo.RoleInfo>) opt.getRoleInfo()).stream()
.map(role -> {
if (StringUtils.isEmpty(role.getTenantCode())) {
return role.getCode();
} else {
return role.getTenantCode() + "." + role.getCode();
}
})
.noneMatch(needRoles::contains))
.orElse(true))) {
String finalToken = token;
boolean pass = roleAuth.keySet().stream()
.filter(strings -> pathMatcher.match(strings, reqUri))
.min(pathMatcher.getPatternComparator(reqUri))
.map(matchedUri -> {
// 找到需要鉴权的URI
if (StringUtils.isEmpty(finalToken)) {
// Token不存在
return false;
}
Set<String> needRoles = roleAuth.get(matchedUri);
return Dew.auth.getOptInfo(finalToken)
.map(opt ->
((Set<OptInfo.RoleInfo>) opt.getRoleInfo()).stream()
.map(role -> {
if (StringUtils.isEmpty(role.getTenantCode())) {
return role.getCode();
} else {
return role.getTenantCode() + ROLE_SPLIT + role.getCode();
}
})
// 是否找到匹配的角色
.anyMatch(needRoles::contains))
// Token在缓存中不存在
.orElse(false);
})
// 该请求URI不需要鉴权
.orElse(true);
if (!pass) {
ErrorController.error(request, response, Integer.parseInt(StandardCode.UNAUTHORIZED.toString()),
String.format("The current[%s][%s] request role is not allowed",
request.getMethod(), request.getRequestURI()), AuthException.class.getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,22 @@ private void testRouter(HttpHeaders headers) {
Assert.assertEquals("403", registerResult.getCode());

// roleAuth
registerResult = testRestTemplate.postForObject("/mgr/register/user", userDTO, Resp.class);
// 没有token
registerResult = testRestTemplate.exchange("/mgr/register/user",
HttpMethod.GET, new HttpEntity<>(null, null), Resp.class).getBody();
Assert.assertEquals("401", registerResult.getCode());
// admin访问只有user允可的url
registerResult = testRestTemplate.exchange("/user/only-user-role/xx",
HttpMethod.GET, new HttpEntity<>(null, headers), Resp.class).getBody();
Assert.assertEquals("401", registerResult.getCode());
// admin访问只有admin允可的url
registerResult = testRestTemplate.exchange("/mgr/register/user",
HttpMethod.GET, new HttpEntity<>(null, headers), Resp.class).getBody();
Assert.assertEquals("404", registerResult.getCode());
// admin访问admin和user允可的url
registerResult = testRestTemplate.exchange("/user/u1",
HttpMethod.GET, new HttpEntity<>(null, headers), Resp.class).getBody();
Assert.assertEquals("404", registerResult.getCode());
}

private void testTokenKind(AuthController.LoginDTO loginDTO) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ dew:
all: ["/mgr/**"]
get: ["/user/**"]
user:
get: ["/user/**"]
get: ["/user/**","/user/only-user-role/**"]
post: ["/user/"]
token-kinds:
DEFAULT:
Expand Down

0 comments on commit 2d93f01

Please sign in to comment.