在Spring Security中接收令牌的基本身份验证

时间:2015-06-08 15:39:01

标签: api rest spring-security jwt

我正在实现RESTful API,用户必须在其中进行身份验证。我希望用户POST他们的凭据以便接收JSON Web令牌(JWT),然后将其用于会话的剩余部分。我没有找到任何好的信息来源来设置它。特别是,我遇到过滤器问题。有没有人有任何信息或教程来帮我设置它?

2 个答案:

答案 0 :(得分:2)

The people at Stormpath have quite a straightforward solution for achieving Oauth. Please take a look at Using Stormpath for API Authentication.

As a summary, your solution will look like this:

  1. You will use the Stormpath Java SDK to easily delegate all your user-management needs.
  2. When the user presses the login button, your front end will send the credentials securely to your backend-end through its REST API.
    1. By the way, you can also completely delegate the login/register/logout functionality to the Servlet Plugin. Stormpath also supports Google, Facebook, LinkedIn and Github login.
  3. Your backend will then try to authenticate the user against the Stormpath Backend and will return an access token as a result:

    /**
     * Authenticates via username (or email) and password and returns a new access token using the Account's ApiKey
     */
    public String getAccessToken(String usernameOrEmail, String password) {
        ApiKey apiKey = null;
        try {
            AuthenticationRequest request = new UsernamePasswordRequest(usernameOrEmail, password);
            AuthenticationResult result = application.authenticateAccount(request);
            Account account = result.getAccount();
            ApiKeyList apiKeys = account.getApiKeys();
            for (ApiKey ak : apiKeys) {
                apiKey = ak;
                break;
            }
            if (apiKey == null) {
                //this account does not yet have an apiKey
                apiKey = account.createApiKey();
            }
        } catch (ResourceException exception) {
            System.out.println("Authentication Error: " + exception.getMessage());
            throw exception;
        }
    
        return getAccessToken(apiKey);
    }
    
    private String getAccessToken(ApiKey apiKey) {
        HttpRequest request = createOauthAuthenticationRequest(apiKey);
        AccessTokenResult accessTokenResult = (AccessTokenResult) application.authenticateApiRequest(request);
        return accessTokenResult.getTokenResponse().getAccessToken();
    }
    
    
    private HttpRequest createOauthAuthenticationRequest(ApiKey apiKey) {
        try {
            String credentials = apiKey.getId() + ":" + apiKey.getSecret();
    
            Map<String, String[]> headers = new LinkedHashMap<String, String[]>();
            headers.put("Accept", new String[]{"application/json"});
            headers.put("Content-Type", new String[]{"application/x-www-form-urlencoded"});
            headers.put("Authorization", new String[]{"Basic " + Base64.encodeBase64String(credentials.getBytes("UTF-8"))});
    
            Map<String, String[]> parameters = new LinkedHashMap<String, String[]>();
            parameters.put("grant_type", new String[]{"client_credentials"});
    
            HttpRequest request = HttpRequests.method(HttpMethod.POST)
                    .headers(headers)
                    .parameters(parameters)
                    .build();
            return request;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
  4. Then, for every authenticated request, your backend will do:

    /** This is your protected API */
    public void sayHello(String accessToken) throws OauthAuthenticationException {
        try {
            if (verify(accessToken)) {
                doStartEngines(); //Here you will actually call your internal doStartEngines() operation
            }
        } catch (OauthAuthenticationException e) {
            System.out.print("[Server-side] Engines not started. accessToken could not be verified: " + e.getMessage());
            throw e;
        }
    }
    
    private boolean verify(String accessToken) throws OauthAuthenticationException {
        HttpRequest request = createRequestForOauth2AuthenticatedOperation(accessToken);
        OauthAuthenticationResult result = application.authenticateOauthRequest(request).execute();
        System.out.println(result.getAccount().getEmail() + " was successfully verified");
        return true;
    }
    
    private HttpRequest createRequestForOauth2AuthenticatedOperation(String token) {
        try {
            Map<String, String[]> headers = new LinkedHashMap<String, String[]>();
            headers.put("Accept", new String[]{"application/json"});
            headers.put("Authorization", new String[]{"Bearer " + token});
            HttpRequest request = HttpRequests.method(HttpMethod.GET)
                    .headers(headers)
                    .build();
            return request;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    

All this will not need any special Spring Security configuration, this is plain Java code that you can run in any framework.

Please take a look here for more information.

Hope that helps!

Disclaimer, I am an active Stormpath contributor.

答案 1 :(得分:1)

这是来自Spring Security OAuth github的工作示例代码。 https://github.com/spring-projects/spring-security-oauth/tree/master/tests/annotation/jwt

您可能甚至不需要弄乱过滤器,如上例所示。如果您有自定义需求,请发布一些示例代码。