更新用户档案时无需用户输入即可保留用户权限的实现方法
用户资料更新导致权限清空的故障解决
故障现象
- 开发实现的用户个人资料更新表单流程,完成用户信息提交、数据落库后,执行登出再重新登录操作时,系统直接提示访问被拒绝
- 全量排查后定位根因:用户表的普通业务字段均可正常保存,但用户关联的权限映射关系会在更新流程中被清空,最终触发权限校验不通过,被系统拦截访问
最初的尝试方向
曾尝试在GSP页面中渲染角色选择复选框,让用户提交时携带角色参数完成关联,对应页面代码如下:
<div class="form-group"> <label class="col-sm-5 control-label">Roles</label> <div class="col-sm-5"> <g:each in="${roles}" var="role" status="i"> <div class="checkbox-inline"> <g:checkBox name="roles" value="${role.id}" checked="${role.authority == "ROLE_MEMBER" ? 'true': user.hasRole(role)}"/> <label for="roles[${i}]">${role.authority}</label> </div> </g:each> </div> </div> <div class="form-group"> <div class="${hasErrors(bean: user, field: 'natureOfIndividual', 'error')} required"> <label for="natureOfIndividual" class="col-sm-5 control-label"> <g:message code="user.natureOfIndividual.label" default="Nature of Individual"/> </label> <div class="col-sm-5"> <g:select name="natureOfIndividual" from="${['Local', 'Foreign']}" class="form-control" noSelection="['': '-----Select-----']" value="${user?.natureOfIndividual}"/> </div> </div> </div>
- 当前这套GSP代码存在复选框无法正常展示的问题,仍在排查阶段
- 最终业务需求完全不需要向普通用户展示角色选择控件,核心目标是实现无用户输入干预的权限自动保留
根因定位
问题根源在UserController.groovy的update方法:方法中原本会调用updateRoles逻辑,该逻辑会先清除用户的所有原有角色关联,再根据前端传入的参数重建角色关联;由于前端未传递有效角色参数,最终直接造成用户权限被清空。
解决方案
注释掉update方法内对updateRoles的调用,用户资料更新流程就不会改动原有角色关联关系,更新完成后用户权限可完整保留。修改后的控制器代码如下:
@Transactional def update(User user) { if (user == null) { transactionStatus.setRollbackOnly() notFound() return } if (user.hasErrors()) { transactionStatus.setRollbackOnly() respond user.errors, view: 'edit' return } boolean passChange = false if (user.isDirty('password')) { passChange = true } user.save flush: true //updateRoles(user) request.withFormat { form multipartForm { if (passChange) { flash.message = "A user with username '${params.username}' and password '${params.password}' has been Updated" } else { flash.message = "Your profile has been updated" } redirect user } '*' { respond user, [status: OK] } } } private updateRoles(User user) { UserRole.removeAll(user) List roleIds = params.roles instanceof String ? [params.roles] : params.roles roleIds?.each { roleId -> def role = Role.get(roleId) UserRole.create(user, role, true) } }
通过上述修改,用户提交资料更新时原有权限不会被改动,可从根源上避免登录时访问被拒绝的问题。
内容的提问来源于stack exchange,提问作者Okello Marvin
相关产品推荐
相关产品推荐

