如何正确设置 Spring 安全匹配器来处理在 URI 中间包含 ID 的请求?

How can I correctly set a Spring Security matcher to handle request containing an ID in the middle of the URI?

我对以下 Spring 安全匹配器表达式感到疯狂。

我有这个控制器 class 包含这个 API

@RestController
@RequestMapping("/api")
@Log
public class WalletController {
    
    @Autowired
    private WalletService walletService;
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private CoinService coinService;

    @Autowired
    private ResourceBundleMessageSource errMessage;
    
    
    @ApiOperation(
              value = "Retrieve the wallets list of a specific user", 
              notes = "Pass the user ID into the URL",
              produces = "application/json")
    @GetMapping(value = "/admin/user/{userID}/wallet", produces = "application/json") 
    public ResponseEntity<List<WalletDTO>> getUserWalletsList(@PathVariable("userID") String userID) throws NotFoundException {
        
        log.info(String.format("****** Retrieve the list of wallets owned by the user: %s *******", userID));
        
        List<WalletDTO> walletsDTOList = this.walletService.getAllWalletsOfAnUser(Integer.parseInt(userID));
        
        return new ResponseEntity<List<WalletDTO>>(walletsDTOList, HttpStatus.OK);
    }
    
    
    .............................................................................................................................................................................................................................................................
    .............................................................................................................................................................................................................................................................
    .............................................................................................................................................................................................................................................................
    OTHER APIs
    .............................................................................................................................................................................................................................................................
    .............................................................................................................................................................................................................................................................
    .............................................................................................................................................................................................................................................................   
    

}

如您所见,API 像这样处理对 URI 的 GET 调用:http://localhost:8019/api/admin/user/54/wallet

现在我有以下匹配器:

private static final String[] CLIENT_MATCHER = { 

                                                    "/api/users/email/*",
                                                    "/api/admin/**",
                                                    "/api/admin/user/*/wallet/"
                                                };

通过这种方式,CLIENT 用户(对 JWT 令牌具有适当的权限)可以正确地从此 API 检索信息(执行控制器方法并且 return 预期输出)。

之所以有效,是因为存在以下规则:"/api/admin/"** 允许调用所有 API 端点以 /api/admin/ 后面跟着其他任何东西(所以像 http://localhost:8019/api/admin/user/54/wallet 是完全允许的) .

我的问题是我真的不想让这种类型的用户(CLIENT 用户)有机会访问我所有的 api 从 /api/admin 开始/ 但我需要像这样的用户可以访问上一个端点。

所以我把之前的matcher改成这样:

private static final String[] CLIENT_MATCHER = { 

                                                    "/api/users/email/*",
                                                    "/api/admin/user/*/wallet"
                                                };

基本上我删除了这条规则:

"/api/admin/**",

我用这个代替了:

"/api/admin/user/*/wallet"

我认为这样做的第二个版本正确地匹配了像 http://localhost:8019/api/admin/user/54/wallet 这样的请求,但它不起作用。使用 Postamn 调用我的 API 我现在收到此错误消息:

{
    "timestamp": "2022-02-10T23:21:47.994+00:00",
    "status": 403,
    "error": "Forbidden",
    "message": "Forbidden",
    "path": "/api/admin/user/54/wallet"
}

将此表达式 -> "/api/admin/user/{userID}/wallet" 放入 CLIENT_MATCHER