You need to enable JavaScript to run this app. 更新用户档案时无需用户输入即可保留用户权限的实现方法
优惠活动
大模型
产品
解决方案
定价
更多

更新用户档案时无需用户输入即可保留用户权限的实现方法

用户资料更新导致权限清空的故障解决

故障现象

  • 开发实现的用户个人资料更新表单流程,完成用户信息提交、数据落库后,执行登出再重新登录操作时,系统直接提示访问被拒绝
  • 全量排查后定位根因:用户表的普通业务字段均可正常保存,但用户关联的权限映射关系会在更新流程中被清空,最终触发权限校验不通过,被系统拦截访问

最初的尝试方向

曾尝试在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.29 07:57:03