gpt4 book ai didi

java - 访问 token 的 Outlook API 在 Java Spring 中返回 400 错误请求

转载 作者:行者123 更新时间:2023-12-02 12:17:20 25 4
gpt4 key购买 nike

  • 代码似乎没有任何错误。
  • 这是一个测试应用,所有 ID 都可用。
  • 在函数 getToken() 中,也可以取消阻止线路调用getScopes() 并进一步尝试。
  • 我有一个带有按钮的index.jsp。
  • 按下按钮“oauthorize”将激活以生成代码和 id_token。
  • 我能够登录,生成代码和 id_token。
  • 这些值显示在带有按钮的“authtoken.jsp”上。
  • 按钮按下后会发布到/common/oauth2/v2.0/token。
  • 在此阶段,Microsoft 页面上会显示 400 个错误请求。

我不确定出了什么问题:

import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.util.UriComponentsBuilder;


@Controller
public class IndexController {

//all oauth2 urls
private static final String authority = "https://login.microsoftonline.com";
private static final String authorizeUrl = authority + "/common/oauth2/v2.0/authorize";
private static final String tokenUrl = authority + "/common/oauth2/v2.0/token";
private static final String redirectUrl = "http://localhost:8080/OutlookProfiles/authtoken";
private static final String reTokenUrl = "http://localhost:8080/OutlookProfiles/showToken";

//credentials
private static final String appId = "7414b3a3-26f1-4928-9d0b-7060d01dd41c";
private static final String appPassword = "cQg9F0EaxuaErNp2YEgYaz8";

private static final String[] scopes = {
"openid",
"offline_access",
"profile",
"User.Read",
"Contacts.Read",
"Mail.Read"
};


@RequestMapping(value = "/index", method = RequestMethod.GET)
public String index(Model model, HttpServletRequest request, HttpServletResponse response){

UUID state = UUID.randomUUID();
UUID nonce = UUID.randomUUID();

// Save the state and nonce in the session so we can
// verify after the auth process redirects back

HttpSession session = request.getSession();
session.setAttribute("expected_state", state);
session.setAttribute("expected_nonce", nonce);

return "index";
}

@RequestMapping(value = "/oauthorize", method = RequestMethod.POST)
public void oauthorize(Model model, HttpServletRequest servletRequest, HttpServletResponse servletResponse) {

try{

UUID state = UUID.randomUUID();
UUID nonce = UUID.randomUUID();

HttpSession session = servletRequest.getSession();
session.setAttribute("expected_state", state);
session.setAttribute("expected_nonce", nonce);
session.setAttribute("error", null);

UriComponentsBuilder urlBuilder = UriComponentsBuilder.fromHttpUrl(authorizeUrl);
urlBuilder.queryParam("client_id", appId);
urlBuilder.queryParam("redirect_uri", redirectUrl);
urlBuilder.queryParam("response_type", "code id_token");
urlBuilder.queryParam("scope", getScopes());
urlBuilder.queryParam("state", state);
urlBuilder.queryParam("nonce", nonce);
urlBuilder.queryParam("response_mode", "form_post");

String locationUri = urlBuilder.toUriString();
System.out.println(locationUri);

servletResponse.sendRedirect(locationUri);

}catch(Exception e){
e.printStackTrace();
}

}


@RequestMapping(value = "/authtoken", method = RequestMethod.POST)
public String authorize(
@RequestParam("code") String code,
@RequestParam("id_token") String idToken,
@RequestParam("state") UUID state,
HttpServletRequest servletRequest,
HttpServletResponse servletResponse) {

// Get the expected state value from the session
HttpSession session = servletRequest.getSession();
UUID expectedState = (UUID) session.getAttribute("expected_state");
UUID expectedNonce = (UUID) session.getAttribute("expected_nonce");


String strState = state.toString().trim().toLowerCase();
String strExState = expectedState.toString().trim().toLowerCase();


// Make sure that the state query parameter returned matches
// the expected state
if (strState.equals(strExState)){
session.setAttribute("authCode", code);
session.setAttribute("idToken", idToken);
System.out.println("Expectedstate : NO Error");
}else {
session.setAttribute("error", "Unexpected state returned from authority.");
System.out.println("\n\nUnexpected state returned from authority.");
}

return "authtoken";
}

@RequestMapping(value = "/getToken", method = RequestMethod.POST)
public void getToken(
HttpServletRequest servletRequest,
HttpServletResponse servletResponse) {

try{

HttpSession session = servletRequest.getSession();
String strCode = (String) session.getAttribute("authCode");

UriComponentsBuilder urlBuilder = UriComponentsBuilder.fromHttpUrl(tokenUrl);
urlBuilder.queryParam("client_id", appId);
urlBuilder.queryParam("client_secret", appPassword);
urlBuilder.queryParam("code", strCode);
urlBuilder.queryParam("redirect_uri", redirectUrl);
urlBuilder.queryParam("grant_type", "authorization_code");
urlBuilder.queryParam("scope", getScopes());

String locationUri = urlBuilder.toUriString();
System.out.println("getToken : " + locationUri);

servletResponse.setHeader("Content-Type", "application/x-www-form-urlencoded");

servletResponse.sendRedirect(locationUri);

}catch(Exception e){
e.printStackTrace();
}
}

@RequestMapping(value = "/showToken", method = RequestMethod.POST)
public String showToken(
@RequestParam("token_type") String code,
@RequestParam("expires_in") String idToken,
@RequestParam("access_token") String accessToken,
//@RequestParam("scope") String paramScope,
HttpServletRequest servletRequest,
HttpServletResponse servletResponse) {

return "getToken";

}

@RequestMapping("/logout")
public String logout(HttpServletRequest request) {
HttpSession session = request.getSession();
session.invalidate();
return "index";
}

private static String getScopes() {
StringBuilder sb = new StringBuilder();
for (String scope: scopes) {
sb.append(scope + " ");
}

String strscope = sb.toString().trim();
System.out.println(strscope);

return strscope;
}
}

400 错误无缘无故地扰乱了我的头脑。

最佳答案

  • 访问 token 的 Microsoft Outlook API 端点:https://login.microsoftonline.com/common/oauth2/v2.0/token需要基于表单的 POST,即 application/x-www-form-urlencoded。
  • 这意味着所有输入参数都应基于表单,而不是附加 url
  • 因此从技术上讲,使用 UriComponentsBuilder 的代码是错误的
  • 代码应改为使用基于 JSON 或基于表单的方法,使用 HttpClient 和 HttpPost 或使用基于 OKHttp3 的 OKHttpClient 和 RequestBody。

我很快就会在这里发布工作代码。

...这是工作代码...

import java.util.List;
import java.util.ArrayList;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.util.UriComponentsBuilder;


@Controller
public class IndexController {

//all oauth2 urls
private static final String authority = "https://login.microsoftonline.com";
private static final String authorizeUrl = authority + "/common/oauth2/v2.0/authorize";
private static final String tokenUrl = authority + "/common/oauth2/v2.0/token";
private static final String redirectUrl = "http://localhost:8080/OutlookProfiles/authtoken";
private static final String reTokenUrl = "http://localhost:8080/OutlookProfiles/showToken";

//credentials
private static final String appId = "7414b3a3-26f1-4928-9d0b-7060d01dd41c";
private static final String appPassword = "cQg9F0EaxuaErNp2YEgYaz8";

private static final String[] scopes = {
"openid",
"offline_access",
"profile",
"User.Read",
"Contacts.Read",
"Mail.Read"
};


@RequestMapping(value = "/index", method = RequestMethod.GET)
public String index(Model model, HttpServletRequest request, HttpServletResponse response){

UUID state = UUID.randomUUID();
UUID nonce = UUID.randomUUID();

// Save the state and nonce in the session so we can
// verify after the auth process redirects back

HttpSession session = request.getSession();
session.setAttribute("expected_state", state);
session.setAttribute("expected_nonce", nonce);

return "index";
}

@RequestMapping(value = "/oauthorize", method = RequestMethod.POST)
public void oauthorize(Model model, HttpServletRequest servletRequest, HttpServletResponse servletResponse) {

try{

UUID state = UUID.randomUUID();
UUID nonce = UUID.randomUUID();

HttpSession session = servletRequest.getSession();
session.setAttribute("expected_state", state);
session.setAttribute("expected_nonce", nonce);
session.setAttribute("error", null);

UriComponentsBuilder urlBuilder = UriComponentsBuilder.fromHttpUrl(authorizeUrl);
urlBuilder.queryParam("client_id", appId);
urlBuilder.queryParam("redirect_uri", redirectUrl);
urlBuilder.queryParam("response_type", "code id_token");
urlBuilder.queryParam("scope", getScopes());
urlBuilder.queryParam("state", state);
urlBuilder.queryParam("nonce", nonce);
urlBuilder.queryParam("response_mode", "form_post");

String locationUri = urlBuilder.toUriString();
System.out.println(locationUri);

servletResponse.sendRedirect(locationUri);

}catch(Exception e){
e.printStackTrace();
}

}


@RequestMapping(value = "/authtoken", method = RequestMethod.POST)
public String authorize(
@RequestParam("code") String code,
@RequestParam("id_token") String idToken,
@RequestParam("state") UUID state,
HttpServletRequest servletRequest,
HttpServletResponse servletResponse) {

// Get the expected state value from the session
HttpSession session = servletRequest.getSession();
UUID expectedState = (UUID) session.getAttribute("expected_state");
UUID expectedNonce = (UUID) session.getAttribute("expected_nonce");


String strState = state.toString().trim().toLowerCase();
String strExState = expectedState.toString().trim().toLowerCase();


// Make sure that the state query parameter returned matches
// the expected state
if (strState.equals(strExState)){
session.setAttribute("authCode", code);
session.setAttribute("idToken", idToken);
System.out.println("Expectedstate : NO Error");
}else {
session.setAttribute("error", "Unexpected state returned from authority.");
System.out.println("\n\nUnexpected state returned from authority.");
}

return "authtoken";
}

@RequestMapping(value = "/getToken", method = RequestMethod.POST)
public void getToken(
HttpServletRequest servletRequest,
HttpServletResponse servletResponse) {

try{

HttpSession session = servletRequest.getSession();
String strCode = (String) session.getAttribute("authCode");

HttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(tokenUrl);
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
List <BasicNameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("client_id", appId));
params.add(new BasicNameValuePair("client_secret", appPassword));
params.add(new BasicNameValuePair("redirect_uri", redirectUrl));
params.add(new BasicNameValuePair("code", strCode));
params.add(new BasicNameValuePair("grant_type", "authorization_code"));

httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");

HttpResponse httpResponse = httpClient.execute(httpPost);
org.apache.http.HttpEntity entity = httpResponse.getEntity();
//String theString = IOUtils.toString(entity.getContent(), "UTF-8");
String strResponse = EntityUtils.toString(entity, "UTF-8");
System.out.println(strResponse);
strResponse = "{\"response\":["+strResponse+"]}";
System.out.println(strResponse);

JSONObject result = new JSONObject(strResponse); //Convert String to JSON Object
JSONArray tokenList = result.getJSONArray("response");
JSONObject objJson = tokenList.getJSONObject(0);
String accessToken = objJson.getString("access_token");
System.out.println(accessToken);

session.setAttribute("accessToken", accessToken);

}catch(Exception e){
e.printStackTrace();
}
}

@RequestMapping(value = "/showToken", method = RequestMethod.POST)
public String showToken(
@RequestParam("token_type") String code,
@RequestParam("expires_in") String idToken,
@RequestParam("access_token") String accessToken,
//@RequestParam("scope") String paramScope,
HttpServletRequest servletRequest,
HttpServletResponse servletResponse) {

return "getToken";

}

@RequestMapping("/logout")
public String logout(HttpServletRequest request) {
HttpSession session = request.getSession();
session.invalidate();
return "index";
}

private static String getScopes() {
StringBuilder sb = new StringBuilder();
for (String scope: scopes) {
sb.append(scope + " ");
}

String strscope = sb.toString().trim();
System.out.println(strscope);

return strscope;
}
}

关于java - 访问 token 的 Outlook API 在 Java Spring 中返回 400 错误请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46060783/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com