簡體   English   中英

Java中的身份驗證問題Oauth2

[英]Authentication issue Oauth2 in java

我的申請有問題。 我的目標是從Java編輯Google電子表格。 但是我在身份驗證方面有問題。 如果我從瀏覽器復制身份驗證代碼,則可以授權自己,但是在我的情況下這不是可行的解決方案。 因此,首先,我想編寫一個簡單的程序來驗證自己的身份,例如:

package com.googleoauth;


import java.io.IOException;

import java.util.ArrayList;

import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.google.common.collect.ImmutableMap;



public class GoogleOauthServer {

private Server server = new Server(8089);

private final String clientId = "141523981682-ee0an7hj3f82rphdud7940v9juniqkch.apps.googleusercontent.com";
private final String clientSecret = "_cCjAG9mlS9KufGzFan4Arni";
private final String callbackUri = "http://localhost:8089/callback";

public static void main(String[] args) throws Exception {
    new GoogleOauthServer().startJetty();
}

public void startJetty() throws Exception {

    ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
    context.setContextPath("/");
    server.setHandler(context);

    // map servlets to endpoints
    context.addServlet(new ServletHolder(new SigninServlet()),"/signin");        
    context.addServlet(new ServletHolder(new CallbackServlet()),"/callback");        

    server.start();
    server.join();
}

class SigninServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {

        // redirect to google for authorization
        StringBuilder oauthUrl = new StringBuilder().append("https://accounts.google.com/o/oauth2/auth")
        .append("?client_id=").append(clientId) // the client id from the api console registration
        .append("&response_type=code")
        .append("&scope=openid%20email") // scope is the api permissions we are requesting
        .append("&redirect_uri=").append(callbackUri) // the servlet that google redirects to after authorization
        .append("&state=this_can_be_anything_to_help_correlate_the_response%3Dlike_session_id")
        .append("&access_type=offline") // here we are asking to access to user's data while they are not signed in
        .append("&approval_prompt=force"); // this requires them to verify which account to use, if they are already signed in

        resp.sendRedirect(oauthUrl.toString());
    }   
}

class CallbackServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
        // google redirects with
        //http://localhost:8089/callback?state=this_can_be_anything_to_help_correlate_the_response%3Dlike_session_id&code=4/ygE-kCdJ_pgwb1mKZq3uaTEWLUBd.slJWq1jM9mcUEnp6UAPFm0F2NQjrgwI&authuser=0&prompt=consent&session_state=a3d1eb134189705e9acf2f573325e6f30dd30ee4..d62c

        // if the user denied access, we get back an error, ex
        // error=access_denied&state=session%3Dpotatoes

        if (req.getParameter("error") != null) {
            resp.getWriter().println(req.getParameter("error"));
            return;
        }

        // google returns a code that can be exchanged for a access token
        String code = req.getParameter("code");

        // get the access token by post to Google
        String body = post("https://accounts.google.com/o/oauth2/token", ImmutableMap.<String,String>builder()
                .put("code", code)
                .put("client_id", clientId)
                .put("client_secret", clientSecret)
                .put("redirect_uri", callbackUri)
                .put("grant_type", "authorization_code").build());

        JSONObject jsonObject = null;

        // get the access token from json and request info from Google
        try {
            jsonObject = (JSONObject) new JSONParser().parse(body);
        } catch (ParseException e) {
            throw new RuntimeException("Unable to parse json " + body);
        }

        // google tokens expire after an hour, but since we requested offline access we can get a new token without user involvement via the refresh token
        String accessToken = (String) jsonObject.get("access_token");

        // you may want to store the access token in session
        req.getSession().setAttribute("access_token", accessToken);

        // get some info about the user with the access token
        String json = get(new StringBuilder("https://www.googleapis.com/oauth2/v1/userinfo?access_token=").append(accessToken).toString());

        // now we could store the email address in session

        // return the json of the user's basic info
        resp.getWriter().println(json);
    }   
}

// makes a GET request to url and returns body as a string
public String get(String url) throws ClientProtocolException, IOException {
    return execute(new HttpGet(url));
}

// makes a POST request to url with form parameters and returns body as a string
public String post(String url, Map<String,String> formParameters) throws ClientProtocolException, IOException { 
    HttpPost request = new HttpPost(url);

    List <NameValuePair> nvps = new ArrayList <NameValuePair>();

    for (String key : formParameters.keySet()) {
        nvps.add(new BasicNameValuePair(key, formParameters.get(key))); 
    }

    request.setEntity(new UrlEncodedFormEntity(nvps));

    return execute(request);
}

// makes request and checks response code for 200
private String execute(HttpRequestBase request) throws ClientProtocolException, IOException {
    HttpClient httpClient = new DefaultHttpClient();
    HttpResponse response = httpClient.execute(request);

    HttpEntity entity = response.getEntity();
    String body = EntityUtils.toString(entity);

    if (response.getStatusLine().getStatusCode() != 200) {
        throw new RuntimeException("Expected 200 but got " + response.getStatusLine().getStatusCode() + ", with body " + body);
    }

    return body;
}
}

當我嘗試此示例時,出現錯誤:401。這是一個錯誤。 錯誤:invalid_client OAuth客戶端已刪除。

我找不到關於此錯誤的任何有用信息。

如果有人可以舉一個例子,那么我可以在沒有任何復制或其他外部干預的情況下授權自己。

謝謝,理查德

我剛剛得到您的示例,並啟動了該應用程序。 瀏覽到localhost:8089 / signin,然后使用google登錄,批准了一些權限,最后我的userinfo得到了json響應。 然后重新啟動應用程序。 該方案仍然有效。 :)

您遇到的問題“可能是”由於您在代碼中使用了一些錯誤的依賴關系而引起的。 我的部門如下:

    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-server</artifactId>
        <version>9.3.0.M1</version>
    </dependency>

    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-servlet</artifactId>
        <version>9.3.0.M1</version>
    </dependency>

    <dependency>
        <groupId>org.apache.clerezza.ext</groupId>
        <artifactId>org.json.simple</artifactId>
        <version>0.4</version>
    </dependency>

    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava-collections</artifactId>
        <version>r03</version>
    </dependency>

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpcore</artifactId>
        <version>4.2.5</version>
    </dependency>

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.2.5</version>
    </dependency>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM