平时我们访问第三方网站的时候,一般都可以使用QQ登录,之类的,网站并不需要你去注册他们的账号,
当QQ服务器告诉网站有这个人的时候,网站就可以给你提供服务.
在国内一般用QQ,微信 比较多.这次用java体验了微软的认证
1.先看看传统的web认证过程
浏览器 提交用户名和密码
网站服务器接收到密码,到数据库中查询
如果正确提供服务
如果错误返回
2.使用微软认证的话,到数据库查询的工作 就没有了 交给了微软去做
先来个简单粗暴的
用户直接把用户名和密码给 tomat,再由tomcat发送给微软认证,请求认证结果.
如果正确,就会有AccessToken 发过来.
tomcat 根据AccessToken 调用Graph Api 就可以获取更多用户的信息
3上服务器端的代码
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.naming.ServiceUnavailableException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import com.microsoft.aad.adal4j.AuthenticationContext;
import com.microsoft.aad.adal4j.AuthenticationResult;
public class PublicClient {
private final static String AUTHORITY = "https://login.partner.microsoftonline.cn/chinainv1.partner.onmschina.cn/";//选择微软的中国区域的服务器
private final static String CLIENT_ID = 填写注册的ClientId;
public static void main(String args[]) throws Exception {
try (BufferedReader br = new BufferedReader(new InputStreamReader(
System.in))) {
System.out.print("Enter username: ");
String username = br.readLine();
System.out.print("Enter password: ");
String password = br.readLine();
AuthenticationResult result = getAccessTokenFromUserCredentials(
username, password);
System.out.println("Access Token - " + result.getAccessToken());
System.out.println("Refresh Token - " + result.getRefreshToken());
System.out.println("ID Token - " + result.getIdToken());
HttpClient httpclient = HttpClients.createDefault();
try
{
// OAuth2 is required to access this API. For more information visit:
// https://msdn.microsoft.com/en-us/office/office365/howto/common-app-authentication-tasks
// Specify values for path parameters (shown as {...})
URIBuilder builder = new URIBuilder("https://graph.chinacloudapi.cn/chinainv1.partner.onmschina.cn/users/sxj@chinainv1.partner.onmschina.cn/?api-version=2013-04-05") ;
// Specify values for the following required parameters
builder.setParameter("api-version", "2013-04-05");
builder.setParameter("user_id", "sxj@chinainv1.partner.onmschina.cn");
builder.setParameter("Authorization", result.getAccessToken());
builder.setParameter("Accept", "application/json;odata=minimalmetadata");
URI uri = builder.build();
HttpGet request = new HttpGet(uri);
HttpResponse response = httpclient.execute(request);
HttpEntity entity = response.getEntity();
if (entity != null) {
System.out.println(EntityUtils.toString(entity));
}
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
}
private static AuthenticationResult getAccessTokenFromUserCredentials(
String username, String password) throws Exception {
AuthenticationContext context = null;
AuthenticationResult result = null;
ExecutorService service = null;
try {
service = Executors.newFixedThreadPool(1);
context = new AuthenticationContext(AUTHORITY, false, service);
Future<AuthenticationResult> future = context.acquireToken(
"https://graph.chinacloudapi.cn/", CLIENT_ID, username, password,
null);
result = future.get();
} finally {
service.shutdown();
}
if (result == null) {
throw new ServiceUnavailableException(
"authentication result was null");
}
return result;
}
}
上面的代码是纯java http代码,也就是说,同样可以使用javaScript/python等其他的语言来模拟发送请求
4.在运行到认证结果的 那一部分 打一个断点 就会发现,其实认证服务器 不仅仅返回了AcessToken
同时我们注意
他还返回了用户的简单的姓名信息,还有
accessToken 的有效期
refleshToken
Id_Token
accessTokenType
等等
注意返回的数据中有一个参数expireson,数值为3600,这个是token的有效期
过一段时间后再用就没有用了
这个时候可以根据AccessToken 来调用Graph Api获取更多的用户信息
比如 get a User , memberOf
但是微软的官网的http请求案例 老是 跑不通,一直以为是坏的
然后我用 PostMan 进行了提交
以Get a user 举例
可以看到 获取了非常多的信息,部门,邮件,手机 等等