You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Spring Controller API角色权限限制并返回前端权限提示?

问题需求

已实现每行带删除按钮的DataTable,后端通过@PreAuthorize("hasRole({'ROLE_ADMIN', 'ROLE_EDITOR'})")校验角色,仅管理员和编辑可执行删除。需要在前端给无权限用户操作删除按钮时,显示权限不足的提示。


方案一:前端预判断用户角色(推荐,减少无效请求)

核心思路:页面渲染时从后端获取当前用户角色,在DataTable渲染删除按钮时,根据角色决定显示正常按钮还是无权限提示/禁用按钮。

步骤1:页面传入用户角色

后端渲染页面时,将当前用户角色存入全局变量或隐藏域:

<!-- 隐藏域方式 -->
<input type="hidden" id="currentUserRole" value="${currentUser.authorities[0].authority}">

<!-- 或全局JS变量 -->
<script>
const CURRENT_USER_ROLE = "${currentUser.authorities[0].authority}";
</script>

步骤2:修改DataTable的渲染逻辑

在columns的render函数中判断角色,动态生成删除按钮:

"render": function (data, type, row) {
    let dropdownMenu = ``;
    let deleteBtn = ``;
    // 判断是否拥有删除权限
    const canDelete = CURRENT_USER_ROLE === 'ROLE_ADMIN' || CURRENT_USER_ROLE === 'ROLE_EDITOR';
    
    if (canDelete) {
        // 有权限:显示正常删除表单
        deleteBtn = `
        <form style="display:inline !important;" action="/admin/delete/" method="post" onsubmit="return confirm('确定要删除员工 ${row.id} 吗?');">
            <input type="hidden" name="id" value="${row.id}" />
            <button class="form-command btn btn-danger btn-sm" type="submit"><i class="fa fa-trash-o"></i></button>
        </form>`;
    } else {
        // 无权限:显示禁用按钮,点击弹提示
        deleteBtn = `
        <button class="form-command btn btn-danger btn-sm disabled" onclick="alert('权限不足,无法执行删除操作');">
            <i class="fa fa-trash-o"></i>
        </button>`;
    }
    return dropdownMenu + "<br/>" + deleteBtn;
}

方案二:异步校验权限后提交(适合角色动态变化场景)

核心思路:点击删除按钮时,先调用后端权限校验接口,确认有权限再执行删除,避免页面暴露角色信息。

步骤1:后端新增权限校验接口

@GetMapping("/admin/check-delete-permission")
@ResponseBody
public boolean checkDeletePermission() {
    // 借助Spring Security自动校验当前用户角色
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    return auth.getAuthorities().stream()
            .anyMatch(grantedAuth -> grantedAuth.getAuthority().equals("ROLE_ADMIN") || grantedAuth.getAuthority().equals("ROLE_EDITOR"));
}

步骤2:前端修改删除逻辑

将表单提交改为异步校验后再执行:

// 权限校验函数
async function validateDeletePermission() {
    try {
        const response = await fetch('/admin/check-delete-permission', {
            method: 'GET',
            headers: {
                [csrfHeader]: csrfToken
            }
        });
        return await response.json();
    } catch (err) {
        console.error('权限校验失败:', err);
        return false;
    }
}

// 处理删除提交
async function handleDelete(event, userId) {
    event.preventDefault(); // 阻止默认表单提交
    if (!confirm(`确定要删除员工 ${userId} 吗?`)) return;
    
    const hasPermission = await validateDeletePermission();
    if (!hasPermission) {
        alert('权限不足,无法执行删除操作');
        return;
    }
    // 有权限则手动提交表单
    event.target.submit();
}

// 修改DataTable的render函数
"render": function (data, type, row) {
    let dropdownMenu = ``;
    const deleteForm = `
    <form style="display:inline !important;" action="/admin/delete/" method="post" onsubmit="return handleDelete(event, ${row.id});">
        <input type="hidden" name="id" value="${row.id}" />
        <button class="form-command btn btn-danger btn-sm" type="submit"><i class="fa fa-trash-o"></i></button>
    </form>`;
    return dropdownMenu + "<br/>" + deleteForm;
}

方案三:拦截后端权限错误提示(兼容现有逻辑)

核心思路:将删除请求改为AJAX提交,全局拦截后端返回的403状态码,统一弹出权限提示。

步骤1:修改前端删除为AJAX请求

// 删除操作函数
function deleteEmployee(userId) {
    if (!confirm(`确定要删除员工 ${userId} 吗?`)) return;
    
    $.ajax({
        url: '/admin/delete/',
        type: 'DELETE',
        contentType: 'application/json',
        headers: {
            [csrfHeader]: csrfToken
        },
        data: JSON.stringify(userId),
        success: function() {
            // 删除成功后刷新DataTable
            $('#tableID').DataTable().ajax.reload();
        },
        error: function(xhr) {
            if (xhr.status === 403) {
                alert('权限不足,无法执行删除操作');
            } else {
                alert('删除失败,请稍后重试');
            }
        }
    });
}

// 修改DataTable的render函数
"render": function (data, type, row) {
    let dropdownMenu = ``;
    const deleteBtn = `
    <button class="form-command btn btn-danger btn-sm" onclick="deleteEmployee(${row.id});">
        <i class="fa fa-trash-o"></i>
    </button>`;
    return dropdownMenu + "<br/>" + deleteBtn;
}

说明

后端@DeleteMapping保持原有逻辑即可,Spring Security在权限不足时会自动返回403状态码,前端通过AJAX的error回调捕获并提示。


内容的提问来源于stack exchange,提问作者Jaiylon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 17:29:56