New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ISSUE #5]Add permission control when loginRequired is true. #6
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zhangjidi2016 LGTM
Coverage decreased (-0.3%) to 79.213% Could you add more UT for this PR?
} | ||
int type = userInfo.getUser().getType(); | ||
// 1:admin 0:ordinary | ||
String loginUserRole = type == 1 ? ADMIN : ORDINARY; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a UserRoleEnum, it seems so many place use it.
if (loginUserRole == ADMIN) { | ||
return joinPoint.proceed(); | ||
} | ||
Map<String, List<String>> map = permissionService.queryRolePerms(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The permission check logic should not be here. It should belongs to PermissionService.
suggest to use
permissionService.checkUriAvailable(uri , userInfo);
In this permission check aspect, just invoke it.
RMQConfigure configure; | ||
|
||
FileBasedPermissionStore fileBasedPermissionStore; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggest to use private but not default.
} | ||
} | ||
|
||
public static class FileBasedPermissionStore { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some duplicate code here, it would be better if we can reuse it.
org.apache.rocketmq.dashboard.service.impl.UserServiceImpl.FileBasedUserInfoStore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I'll re-optimize the code as suggested.
doc/1_0_0/UserGuide_CN.md
Outdated
``` | ||
* 2.确保${rocketmq.config.dataPath}定义的目录存在,并且该目录下创建登录配置文件"role-permission.yml", | ||
如果该目录下不存在此文件,则默认使用resources/role-permission.yml文件。改文件保存了普通用户角色所有能访问的接口地址。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
改-> 该
如果resources/role-permission.yml也不存在,会怎样?请把错误的退避规则描述的更精致一些:-)
doc/1_0_0/UserGuide_CN.md
Outdated
- /dashboard/topic.query | ||
- /dashboard/topicCurrent | ||
.... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
考虑通配支持,后续维护太复杂否则
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, the interface path in the authentication file is added with wildcard characters
doc/1_0_0/UserGuide_CN.md
Outdated
.... | ||
``` | ||
* 3.前端页面显示上,为了更好区分普通用户和admin用户权限,关于资源的删除、更新等操作按钮不对普通用户角色显示。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
考虑重签功能,要么退出换角色登入,要么支持管理员到普通账户的一键切换
doc/1_0_0/UserGuide_EN.md
Outdated
ordinary: | ||
- /rocketmq/nsaddr | ||
- /ops/homepage.query |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change description corresponds with CN.
@@ -37,6 +38,7 @@ | |||
|
|||
@Controller | |||
@RequestMapping("/consumer") | |||
@Permission |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still recommend using the unified configuration, which can be unified in one directory, without annotating each method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The @Permission annotation is on a class in which all the methods of the class will implement aop methods. There is no need to annotate each method
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface Permission { | ||
|
||
String value() default ""; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be helpful if we could leave the concrete field in here. such as read-only, write...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This value attribute is not used, then delete
* can also be applied to methods in a class for fine control | ||
*/ | ||
@Pointcut("@annotation(org.apache.rocketmq.dashboard.permisssion.Permission) || @within(org.apache.rocketmq.dashboard.permisssion.Permission)") | ||
private void permission() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does within[1] annotation work well here?
[1] https://docs.spring.io/spring-framework/docs/2.0.x/reference/aop.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes,it can work,@Within - limits matching to join points within types that have the given annotation (the execution of methods declared in types with the given annotation when using Spring AOP).
load(inputStream); | ||
} | ||
} else { | ||
log.info(String.format("User Permission configure file is %s", filePath)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any resource leak if we do not use try with?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I will close the InputStream after use
@zhangjidi2016 there are many places waiting to be clarified. BTW, do we have a better way to support here. do not link permission to URL directly? |
I haven't thought of any other good authentication methods yet. However, regardless of the authentication method, we need to maintain the role-permission mapping, because rocketMQ-Dashboard deployment does not depend on any external storage system, only to save the mapping to a disk file. |
One trick is you could store it in one topic if it is necessary, but it is not friendly for updates, it invokes me to think about our compact topic design... |
I come up with an idea for improving authentication.
Maybe we can introduce permission
user have role, role contains several permissions. A login user can have a permission set. For backend: invoke create topic method requires topic_write permission ==> (we can add @Permission(value = "topic_write") to the create topic method) For front end: show create topic button requires topic_write permission ==> (we can get permissions after login,only show create topic button if the user has topic_write permission) Do you have any suggestions? |
Local file storage is indeed a problem. Because of it, we need to stand-alone deployment, or the config can not sync. It is better to have a remote shared storage, Maybe we should abstract the storage interface, local file storage is an implementation(for now), mysql is another implementation, MQ message implementation etc. |
Agree, specifically speaking, we could learn lessons from RBAC, here resources may have different operations |
@zhangjidi2016 |
Well, we can merge this PR first, and verify permissions according to the interface path in the first version, and then optimize this problem again according to the structure of RBAC. |
@zhangjidi2016 |
OK,code conflicts have been resolved |
What is the purpose of the change
#5
When the login user calls all interfaces, the permission of each interface is verified by AOP, by checking whether the role to which the user belongs has the access permission of the interface. All interface urls that a common user role has access permissions are saved in a file. The file is hot updated to facilitate adding or deleting permissions.
Brief changelog
XX
Verifying this change
XXXX
Follow this checklist to help us incorporate your contribution quickly and easily. Notice,
it would be helpful if you could finish the following 5 checklist(the last one is not necessary)before request the community to review your PR
.[ISSUE #123] Fix UnknownException when host config not exist
. Each commit in the pull request should have a meaningful subject line and body.mvn -B clean apache-rat:check findbugs:findbugs checkstyle:checkstyle
to make sure basic checks pass. Runmvn clean install -DskipITs
to make sure unit-test pass. Runmvn clean test-compile failsafe:integration-test
to make sure integration-test pass.