RESTful 認証サービスを構築していますが、接続に問題があります。応答を取得しようとすると、恐ろしい「サーバーから返された HTTP 応答コード: 400」が表示されます。これは非常に奇妙に思えます。リクエストを送信するときにこのエラーが発生すると思います。
このサービスを Spring-Security AuthenticationProvider の一部として使用しています。現在、テスト用の実際のサービスではなく、シミュレーターを使用しています。シミュレーターにもサービスにも接続しません。
呼び出し方法は次のとおりです。
public <T> T invoke(String service, Object request, Class<T> responseType) throws IOException {
ObjectMapper mapper = new ObjectMapper();
URL url = new URL("http://localhost:8888/simulator/rest" + service);
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
uc.setRequestMethod("POST");
uc.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
uc.setDoOutput(true);
uc.setDoInput(true);
uc.connect();
OutputStream out = uc.getOutputStream();
mapper.writeValue(out, request);
out.close();
return mapper.readValue(uc.getInputStream(), responseType);
}
このメソッドを呼び出すコードは次のとおりです。
UsernamePasswordAuthenticationToken token =
new UsernamePasswordAuthenticationToken("thomas", "thomas");
UsernamePasswordAuthenticationToken response =
invoke("/authenticate", token, UsernamePasswordAuthenticationToken.class);
呼び出されるシミュレーター メソッドは次のとおりです。
@RequestMapping(value = "/authenticate", method = RequestMethod.POST)
@ResponseBody
public UsernamePasswordAuthenticationToken authenticate(
@RequestBody UsernamePasswordAuthenticationToken userNameAndPassword) {
String userName = (String) userNameAndPassword.getPrincipal();
String password = (String) userNameAndPassword.getCredentials();
if (userName.equalsIgnoreCase("thomas")) {
if (userName.equals(password)) {
UsernamePasswordAuthenticationToken response =
new UsernamePasswordAuthenticationToken(
userName,
password,
new ArrayList<GrantedAuthority>());
return response;
}
}
return new UsernamePasswordAuthenticationToken(userName, password);
}
エラーの原因となる行は次のとおりです。
mapper.readValue(uc.getInputStream(), responseType);
このコードに問題が見られない場合。ずっと眺めていたに違いない。問題に新しい目が必要です。
ところで、この REST サービスとシミュレーターは、他の操作で正常に使用されています。
追加情報:
エラーは uc.getInputStream() 呼び出しで発生します。HttpURLConnection.inputStream = null。
また、リクエストのヘッダーは次のとおりです。
これが役立つ場合、このリクエストのヘッダーは次のとおりです。
[WARN] 400 - POST /simulator/rest/authenticate (127.0.0.1) 1417 bytes
Request headers
Content-Type: application/json;charset=UTF-8
X-Tenant: 1
Authorization: 0000013770b132a1dfcbfe0a694542b244534e0e406cfa857660c904daa89af91d0ac769
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.6.0_26
Host: localhost:8888
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 112
Response headers
Set-Cookie: JSESSIONID=1r02p7yvm8mzs;Path=/
X-UA-Compatible: IE=9
Content-Type: text/html; charset=iso-8859-1
Content-Length: 1417
これが私のトークンコードです:
import java.util.List;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
public class SerializedAuthenticationToken extends UsernamePasswordAuthenticationToken {
private static final long serialVersionUID = 2783395505630241326L;
private Object principal;
private Object credentials;
/**
* no-arg constructor to satisfy Serializable.
*/
public SerializedAuthenticationToken() {
super(null, null);
}
/**
* constructor.
*/
public SerializedAuthenticationToken(Object principal, Object credentials) {
super(null, null);
setPrincipal(principal);
setCredentials(credentials);
}
/**
* constructor with List<GrantedAuthorities>.
*/
public SerializedAuthenticationToken(Object principal, Object credentials, List<GrantedAuthority> authorities) {
super(null, null, authorities);
setPrincipal(principal);
setCredentials(credentials);
}
public Object getPrincipal() {
return principal;
}
public void setPrincipal(Object principal) {
this.principal = principal;
}
public Object getCredentials() {
return credentials;
}
public void setCredentials(Object credentials) {
this.credentials = credentials;
}
public void setName(Object name) {
}
}
また、新しいスタック トレースを取得しています。
org.codehaus.jackson.map.JsonMappingException: Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead (through reference chain: com.mckesson.shared.util.SerializedAuthenticationToken["authenticated"])