我正在开发一个Spring Boot RESTful应用程序,它将为Web应用程序公开一堆API,以对资源执行CRUD操作。
我正在使用spring-data-rest
(当然还有spring-data-jpa
)借助Spring Magic公开实体/存储库。
即使我已经使用spring-security来保护(基于角色)端点,它也不是完全安全的。
例如:我有一个User
实体,该实体与one-to-many
之间具有Car
关系。因此,获取用户汽车的端点(spring-data-rest
公开的汽车)为localhost:8080/users/{userId}/cars
但是,具有所需角色的任何用户都可以通过另一个用户的userId
并仍然访问端点。我想要的行为是以某种方式保护这些端点的安全,如果我登录的用户ID为1
,那么我们只能命中localhost:8080/users/1/cars。具有其他任何userId
的任何其他请求都应以403
或其他形式结束。
注:我知道,如果编写自己的控制器,则可以获取主体的句柄并执行我想要的操作。我只想知道spring-data-rest
中有没有一种方法或模式可以实现这一目标?
要实现这一点,您需要编写一个Interceptor
。它将在以下情况下使用:
将请求发送到控制器之前
将响应发送到客户端之前
在写入任何Interceptor
之前,它应该实现HandlerInterceptor
接口。Interceptor
支持的三种方法是:
preHandle()
方法-在发送请求之前执行操作到controller
。此方法应返回true以返回对客户的回应。postHandle()
方法-用于在发送之前执行操作对客户的回应。afterCompletion()
方法-用于执行操作完成请求和回复后。代码:
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(
HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// By using a Context do your calculation like userId incoming is same as loggedInUserId ( From Context ) etc
//here I am just illustrating whether header is missing in incoming request. I have named my header as Authorization.
if (request.getHeader("Authorization") == null){
throw new HttpUnauthorizedException("Authorization header missing");
return false;
}else
return true;
}
@Override
public void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler,
) throws Exception {}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception exception) throws Exception {}
}
通过使用InterceptorRegistry
,您可以像下面这样注册Interceptors
:
@Component
public class ProductServiceInterceptorAppConfig extends WebMvcConfigurer{
@Autowired
MyInterceptor myInterceptor ;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor );
}
}
有关详细信息,请点击此链接Interceptors