OAuth2协议是什么
OAuth协议致力于 使网站和应用程序(统称为消费方)能够在无须用户透露其认证证书的情况下,通过API访问某个web服务(统称为服务提供方)的受保护资源。
OAuth允许用户提供一个令牌给第三方网站,一个令牌对应一个第三方网站,该令牌能在特定的时间内访问特定的资源。
https://tools.ietf.org/html/rfc6749 具体步骤
OAuth2协议提供四种常用授权方式
翻译一下:
我们主要讲授权码模式。
主要分两步:
1.获取code
客户端跳转到服务器url, 四个参数:response_type,client_id,redirect_uri,scope。
服务端相应,回调, 跳转到redirect_uri , 带参数code
code是服务端发放的同意许可。
2.根据code获取token
客户端发送ajax请求,四个参数:grant_type,code,redirect_uri,scope 。认证信息client_id+client_secret
服务端返回token信息。
有了token你就可以为所欲为了。
客户端访问资源服务器接口, 添加参数Authorization = token_type+" "+access_token;
---------------------------------------------------------------------------------分割线-------------------------------------------------------------------------------------------
SpringSecurityOauth2 是结合SpringSecurity封装了OAuth2相关流程.
引入jar包
<!-- 引入Web模块 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
认证服务器:
@EnableAuthorizationServer
package com.zzy.demo.config.oauth;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
@Configuration
@EnableAuthorizationServer
public class MyOauthServerConfig {
}
are you kidding me!!! 为何如此简单? 就是这么简单 !
这意味着, 本服务已经是一个认证服务器. 可以发Oauth2证书(token)了..
资源服务器:
@EnableResourceServer
package com.zzy.demo.config.oauth;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
@Configuration
@EnableResourceServer
public class MyResourceServerConfig {
}
这意味着当前服务的rest请求,都被保护起来了!
sso:
@EnableOAuth2Sso
这个也很简单,我们下回分解.
再次强调, 以上三个注解,必须在SpringSecurity环境下用.
下面我们模拟一个获取token的流程.
认证服务器端需要做两件事
1. @EnableAuthorizationServer 上面我们说过
2. 配置可被授权的客户端信息, 在application.properties中加入clientId,clientSecret.
security.oauth2.client.clientId=client1
security.oauth2.client.clientSecret=123456
客户端需要做三件事
1. 跳转到服务器url, 获取code
2. 根据code获取token
3. 根据token,访问资源服务器数据.
@Controller
@RequestMapping("/client")
public class DemoController {
String ssoServerUrl="http://localhost:9999/server";
String client_id="client1";
String client_secret="123456";
String redirect_uri="http://127.0.0.1:8011/client/oauth/token";
String grant_type="authorization_code";
@RequestMapping("/login")
public String login(HttpServletRequest request, HttpServletResponse response, Model model) {
//http://localhost:8888/oauth/authorize?response_type=code&client_id=yue&redirect_uri=http://guokaige.com&scope=all
String queryString="response_type=code"+
"&client_id="+client_id+
"&redirect_uri="+redirect_uri+
"&scope=all";
String str=ssoServerUrl+"/oauth/authorize?"+queryString;
System.out.println("------------------"+str+"----------------------");
return "redirect:"+str;
}
/**
*
* 通过code换取token
* @param code
* @return
* @throws IOException
*/
@RequestMapping(value = "/oauth/token")
@ResponseBody
public String token(String code) throws IOException {
System.out.println("------------获取到code---------------"+code);//将请求得到的code输出到控制台
String token_url = ssoServerUrl+"/oauth/token";
String token = getToken(token_url,code);
System.out.println("------获取到token--------"+token);//将通过code获取的access_token输出到控制台
String userinfo_url=ssoServerUrl+"/user/index.json";
String userInfo = getUserInfo(userinfo_url,token);
System.out.println("------获取到userInfo--------"+userInfo);//将通过code获取的access_token输出到控制台
return userInfo;
}
public String getToken(String url,String code) {
Map<String, Object> params =new HashMap<String, Object>();
params.put("grant_type", grant_type);
params.put("code", code);
params.put("redirect_uri", redirect_uri);
params.put("scope", "all");
// POST请求
HttpResponse response = HttpRequest
.post(url)
.basicAuthentication(client_id, client_secret)
.form(params)
.header("Content-Type", "application/x-www-form-urlencoded")
.send();
//System.out.println("--------------------"+response.toString());
return response.bodyText();
}
public String getUserInfo(String url,String token) {
JSONObject json = JSONObject.parseObject(token);
String token_type = json.getString("token_type");
String access_token=json.getString("access_token");
String authorization=token_type+" "+access_token;
System.out.println("------Authorization:"+authorization);
// POST请求
HttpResponse response = HttpRequest
.post(url)
//.basicAuthentication(client_id, client_secret)
.header("Content-Type", "application/x-www-form-urlencoded")
.header("Authorization",authorization )
.send();
//System.out.println("--------------------"+response.toString());
return response.bodyText();
}
}
我们来跑一下看看效果
首先客户端端口是8011, 认证服务器端口9999 ,server.context-path=/server
1.访问客户端http://localhost:8011/client/login, 浏览器跳转到认证服务器登录页面http://localhost:9999/server/login,
登陆完成后, 浏览器跳转 http://127.0.0.1:8011/client/oauth/token?code=IPbA7v
2.我们已经得到code, 我们来获取token。访问认证服务器 http://localhost:9999/server/oauth/token
public String getToken(String url,String code) {
Map<String, Object> params =new HashMap<String, Object>();
params.put("grant_type", grant_type);
params.put("code", code);
params.put("redirect_uri", redirect_uri);
params.put("scope", "all");
// POST请求
HttpResponse response = HttpRequest
.post(url)
.basicAuthentication(client_id, client_secret)
.form(params)
.header("Content-Type", "application/x-www-form-urlencoded")
.send();
//System.out.println("--------------------"+response.toString());
return response.bodyText();
}
3.拿到token后,我们访问资源服务器
public String getUserInfo(String url,String token) {
JSONObject json = JSONObject.parseObject(token);
String token_type = json.getString("token_type");
String access_token=json.getString("access_token");
String authorization=token_type+" "+access_token;
System.out.println("------Authorization:"+authorization);
// POST请求
HttpResponse response = HttpRequest
.post(url)
//.basicAuthentication(client_id, client_secret)
.header("Content-Type", "application/x-www-form-urlencoded")
.header("Authorization",authorization )
.send();
//System.out.println("--------------------"+response.toString());
return response.bodyText();
}
有什么不懂欢迎评论.