Calling a REST web service secured with Spring Sec

2020-02-22 07:37发布

问题:

I'm hosting a REST web service in a Grails application, using Spring Security, i.e.:

@Secured(['IS_AUTHENTICATED_REMEMBERED'])
def save = {
    println "Save Ride REST WebMethod called"
}

I'm calling it from an Android app. (Calling the unsecured service works just fine.)

To call the service, I'm manually building up a request (HttpUriRequest) and executing it with an HttpClient.

I'm wondering what the best practices are, and how to implement them... Specifically, should I:

  1. Perform a login once, to retrieve a JSESSION_ID, then add a header containing it into the HttpUriRequest for each subsequent request?
  2. Or (not sure how I would even do this) include the login and password directly on each request, foregoing the cookie/server-side session

I think I can get option 1 working, but am not sure if Spring Security permits (2), if that's the way to go... Thanks!

--also, there isn't any library I'm missing that would do all this for me is there? :)

回答1:

Spring security does support both basic authentication and form based authentication (embedding the username/password in the URL).

A REST service is generally authenticated on each and every request, not normally by a session. The default spring security authentication (assuming you're on 3.x) should look for basic authentication parameters or form parameters (j_username and j_password) (in the form http://you.com/rest_service?j_username=xyz&j_password=abc).

Manually tacking the j_username/j_password onto the URL, adding them as post parameters (I believe), or setting the basic authentication username/password should all work to authenticate a REST service against the default Spring Security interceptors, right out of the box.

I will admit that I haven't tried this on REST services, though I do clearly recall reading exactly this in the docs as I did the same for basic page logins on spring security recently. Disclaimer over.



回答2:

I think you can use a login-once-and-get-a-token method that's similar to how oauth works.

sending username and password across the network outside of secured channel(https/ssl) is a terrible idea. anyone on the network can sniff your request package and see the clear text password.

on the other hand, if you use a token method, since the token string is randomly generated, even the token is compromised, the worst case is someone can use the token accessing your REST API.

another solution is going through ssl tunnel(HTTPS). i have actually done a comparison and result shows: 80 requests/min(https) vs 300 requests/min(http)