3

我们正在使用带有 Java 的 Stormpath,并且还尝试在同一个应用程序上将表单登录与 REST API 身份验证结合起来。

我已经按照这里的描述设置了stormpath servlet插件https://docs.stormpath.com/java/servlet-plugin/quickstart.html ...这工作得很好。

现在,在同一个应用程序上,我们有 API,我在其中使用 Stormpath 实现了 oAuth 身份验证,请参见此处http://docs.stormpath.com/guides/api-key-management/

Basic Base64(keyId:keySecret)通过在请求标头和grant_type = client_credentials正文中发送访问令牌的第一个请求可以正常工作。访问令牌被很好地返回。但是,在返回以下 json 错误消息之前,尝试使用标头验证后续请求Bearer <the-obtained-access-token>甚至不会命中应用程序...

{
    "error": "invalid_client",
    "error_description": "access_token is invalid."
}

这很令人困惑,因为我在整个应用程序中都设置了断点,而且我很确定在stormpath 启动并返回此错误之前,API 请求不会到达应用程序中的任何位置。即使stormpath在到达REST接口之前以某种方式拦截了请求,这条消息对我来说也没有任何意义,因为我肯定会使用从第一次调用中获得的有效访问令牌进行后续API调用以获取访问权限-令牌。

我已经不知道为什么会发生这种情况,但我怀疑它可能与stormpath配置有关,尤其是与表单登录/身份验证的Web视图和oAuth身份验证相结合的REST端点。话虽如此,这就是我的stormpath.properties 的样子。希望这可以帮助指出我可能做错的任何事情。

stormpath.application.href=https://api.stormpath.com/v1/applications/[app-id]
stormpath.web.filters.authr=com.app.security.AuthorizationFilter
stormpath.web.request.event.listener = com.app.security.AuthenticationListener

stormpath.web.uris./resources/**=anon
stormpath.web.uris./assets/**=anon
stormpath.web.uris./v1.0/**=anon
stormpath.web.uris./** = authc,authr
stormpath.web.uris./**/**=authc,authr

对此的帮助将不胜感激。

4

2 回答 2

2

该问题可能与不正确的请求有关。

您是否可以在您的应用程序中尝试此代码?:

 private boolean verify(String accessToken) throws OauthAuthenticationException {
     HttpRequest request = createRequestForOauth2AuthenticatedOperation(accessToken);
     AccessTokenResult result = Applications.oauthRequestAuthenticator(application)
        .authenticate(request);
     System.out.println(result.getAccount().getEmail() + " was successfully verified, you can allow your protect operation to continue");
     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;
     }
 }
于 2015-11-09T14:00:33.613 回答
1

我准备了一个示例来演示 oauth 令牌的创建以及使用访问令牌对受保护页面的授权访问。

它建立在 Stormpath SDK 中的 servlet 示例之上。可以在这里找到回购:https ://github.com/stormpath/stormpath-java-oauth-servlet-sample

它演示了运行 servlet 应用程序并让带外程序获取和使用 oauth 令牌来访问受保护的资源。

oauth 部分的核心在TokenAuthTest.java

public class TokenAuthTest {
    public static void main(String[] args) throws Exception {

        String command = System.getProperty("command");

        if (command == null || !("getToken".equals(command) || "getPage".equals(command))) {
            System.err.println("Must supply a command:");
            System.err.println("\t-Dcommand=getToken OR");
            System.err.println("\t-Dcommand=getPage OR");
            System.exit(1);
        }

        if ("getToken".equals(command)) {
            getToken();
        } else {
            getPage();
        }
    }

    private static final String APP_URL = "http://localhost:8080";
    private static final String OAUTH_URI = "/oauth/token";
    private static final String PROTECTED_URI = "/dashboard";

    private static void getToken() throws Exception {
        String username = System.getProperty("username");
        String password = System.getProperty("password");

        if (username == null || password == null) {
            System.err.println("Must supply -Dusername=<username> -Dpassword=<password> on the command line");
            System.exit(1);
        }

        PostMethod method = new PostMethod(APP_URL + OAUTH_URI);

        method.setRequestHeader("Origin", APP_URL);
        method.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

        method.addParameter("grant_type", "password");
        method.addParameter("username", username);
        method.addParameter("password", password);

        HttpClient client = new HttpClient();
        client.executeMethod(method);

        BufferedReader br = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream()));
        String readLine;
        while(((readLine = br.readLine()) != null)) {
            System.out.println(readLine);
        }
    }

    private static void getPage() throws Exception {
        String token = System.getProperty("token");

        if (token == null) {
            System.err.println("Must supply -Dtoken=<access token> on the command line");
            System.exit(1);
        }

        GetMethod method = new GetMethod(APP_URL + PROTECTED_URI);
        HttpClient client = new HttpClient();

        System.out.println("Attempting to retrieve " + PROTECTED_URI + " without token...");

        int returnCode = client.executeMethod(method);
        System.out.println("return code: " + returnCode);

        System.out.println();

        System.out.println("Attempting to retrieve " + PROTECTED_URI + " with token...");

        method.addRequestHeader("Authorization", "Bearer " + token);
        returnCode = client.executeMethod(method);
        System.out.println("return code: " + returnCode);
    }
}
于 2015-11-11T21:35:30.900 回答