如何基于用户的角色实现对Spring控制器API的访问限制,并将消息发送回用户?

gev0vcfq  于 5个月前  发布在  Spring
关注(0)|答案(1)|浏览(42)

我已经实现了一个DataTable配置,每行都有一个删除按钮。然而,删除按钮的功能仅限于具有特定角色的用户,例如“ADMIN”。没有“ADMIN”或“EDITOR”角色的用户在尝试使用删除按钮时会遇到一个提示,通知他们未经授权的访问。
这是一个按钮,它被呈现在我的DataTable列中:

<form style="display:inline !important;" action="/admin/delete/" method="post" onsubmit="return confirm('Do you really want to delete employee ${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>`;

字符串
这是控制器类中的删除API:

@PreAuthorize("hasRole({'ROLE_ADMIN', 'ROLE_EDITOR'})")
    @DeleteMapping("delete")
    @ResponseStatus(HttpStatus.OK)
    void delete(@RequestBody Integer id) {
        deleteEntity(id);
    }


@PreAuthorize注解应该检查经过身份验证的用户的角色,如果他们没有被授权,则拒绝他们。事情是这样的,我想向前端用户发送一条消息,告诉他们他们没有删除行的权限。

$(document).ready(function () {
    $('#tableID').DataTable({
        "processing": true,
        "serverSide": true,
        "ajax": {
            "url": "api-endpoint",
            "type": "POST",
            'beforeSend': function (xhr) {
                xhr.setRequestHeader(csrfHeader, csrfToken);
            },
            'data': function (d) {
                d.search.value = d.search.value || '';
                d.columns[2]['search']['value'] = d.columns[2]['search']['value'] || '';
                d.columns[3]['search']['value'] = d.columns[3]['search']['value'] || '';
                d.columns[4]['search']['value'] = d.columns[4]['search']['value'] || '';
            },
        },
        "columns": [
            // ... (other columns remain unchanged)
        {
                    "data": null,
                    "render": function (data, type, row) {
                        let dropdownMenu = ``;
                        let deleteForm = `
                        <form style="display:inline !important;" action="/admin/delete/" method="post" onsubmit="return confirm('Do you really want to delete employee ${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;
                    },
                    "orderable": false
                }
            
        ],
        initComplete: function () {
            // ... (unchanged)
        }
    });
});


我如何才能做到这一点?

yyyllmsg

yyyllmsg1#

你可以通过实现一个GlobalExceptionHandler来完成这个任务。下面是一个示例代码片段:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity<ProblemDetail> handleAccessDeniedException(AccessDeniedException e) {
        ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.UNAUTHORIZED, e.getMessage());
        problemDetail.setTitle("Requested Resource is UNAUTHORIZED");
        return new ResponseEntity<>(problemDetail, HttpStatus.UNAUTHORIZED);
    }

}

字符串
这段代码使用@ControllerAdvice annotation定义了一个GlobalExceptionHandler。它包括一个使用@ExceptionHandler annotation的AccessDeniedException的特定异常处理方法。该方法构造了一个ProblemDetail对象,其中包含有关未授权访问的详细信息,并在一个ResponseEntity中返回它,状态为401 (UNAUTHORIZED)
此代码生成的响应类似于以下JSON结构:

{
  "type": "about:blank",
  "title": "Requested Resource is UNAUTHORIZED",
  "status": 401,
  "detail": "Access Denied",
  "instance": "/api/secured"
}

相关问题