問題描述
帶有 spring‑security 的 OAuth2 ‑ 通過 HTTP 方法限制 REST 訪問 (OAuth2 with spring‑security ‑ limit REST access by HTTP method)
So we've implemented the OAuth2 ‑ client credentials grant between our REST server and a client application server using spring‑security . The client can access its resources with the token it gets using client credentials authentication.
What I don't get are the Scopes I can set up for a client and the resources.
I explicitly said, Client A has Role X with Scope READ and I said Resource U can be accessed with Role X and Scope READ. Now I expect the resource to reject any DELETE
or POST
request but apparently I am mistaken. If I send a HTTP DELETE
to Resource U it will get through.
So it looks like the Scopes are meaningless in my setup. How can I make use of them?
Or do I still need to limit access at the resource itself as I suggested below?
Snippets from our setup:
<oauth:client‑details‑service id="clientDetails">
<oauth:client client‑id="the_client"
authorized‑grant‑types="client_credentials" authorities="ROLE_CLIENT"
scope="read" secret="secret" />
</oauth:client‑details‑service>
<http pattern="/rest/**" create‑session="never"
entry‑point‑ref="oauthAuthenticationEntryPoint"
access‑decision‑manager‑ref="accessDecisionManager"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept‑url pattern="/rest/persons" access="ROLE_CLIENT,SCOPE_READ" />
<custom‑filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access‑denied‑handler ref="oauthAccessDeniedHandler" />
</http>
The REST resource:
@Path("/persons")
@Named
public class PersonRest {
@GET
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces({ MediaType.APPLICATION_JSON })
public Response getAll(@Context UriInfo uriInfo) {
// ...
}
@DELETE
@Path("/{id}")
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_JSON)
@Transactional
public Response delete(@PathParam("id") String id) {
// ...
}
Is there any "simple" configuration to tell spring security on the server side, that ROLE_READ should allow only GET requests?
Or do I need some @PreAuthorize
annotation or context setup for the specific resource?
So, would something like that work: ?
@PreAuthorize("hasScope(read)")
@DELETE
@Path("/{id}")
// ...
public Response delete(@PathParam("id") String id) {
Though that would be horrible news if I had to do it this way as then I'd have to configure each resource individually...
Maybe I can make use of some filter?
Thanks for any help with this!
‑‑‑‑‑
參考解法
方法 1:
Why can't you use
@RolesAllowed({"customRole"})
to protect your HTTP Method , and convert Oauth scope to {customRole} using a Filter
or have you tried
<security:intercept‑url pattern="/rest/persons" access="hasAnyRole('ROLE_USER_READ')" method="GET"/>
or something similar
(by Pete、TheWhiteRabbit)