OAuth2.0认证demo示例
一、Oauth2.0接口说明
说明:
接入前请确保已在SourceID中开通相关用户或应用及权限
特点及应用场景:
1.授权码模式:安全性高,使用率高,流程复杂。要求第三方应用必须有服务器。对安全性要求较高,web项目中一般使用授权码模式 2.密码模式:需要输入账号密码,极度不安全,需要高度信任第三方应用 适用于其他授权模式都无法采用的情况;原生APP可以使用,web不建议使用 3. 客户端模式:授权维度为应用维度,而不是用户维度。因此有可能多个用户共用一个Token的情况。适用于应用维度的共享资源。适用于服务器之间交互,不需要用户参与。
1、密码模式
1.1、原理说明
说明:
1-2、向CAS服务端请求accessToken接口,服务端将返回access_token、expires_in、refresh_token这三个信息,需要将这三个值保存起来。其中access_token为令牌,expires_in为令牌失效时间,refresh_token为备用令牌。
3、访问CAS服务端的相关接口时只需要携带access_token就可以访问。
4、当令牌在expires_in时间之内没有操作将失效,需要通过refresh_token来刷新令牌。
5、安全要求高的应用系统,对接中请求支持post请求方式时,请使用post请求,身份平台使用https部署,保证数据在传输过程不被拦截。
1.2、方法说明
1.2.1、获取令牌接口:
注意:安全要求高时,请求方式使用POST进行请求。
请求路径 | 请求方法 | 参数 | 描述 |
---|---|---|---|
/oauth2.0/accessToken | POST | grant_type=password&client_id= |
密码模式 |
入参字段说明:
参数名 | 是否必传 | 说明 |
---|---|---|
grant_type | 是 | 密码模式为password |
client_id | 是 | 应用账号 |
username | 是 | 用户名 |
password | 是 | 密码 |
scope | 否 | 权限列表,以空格分隔,空为默认(以服务端为准) |
返回值说明:
参数名 | 说明 |
---|---|
access_token | 访问令牌 |
access_type | 令牌类型 |
expires_in | 令牌有效期 |
refresh_token | 刷新令牌 |
返回数据示例:
{
"access_token": "AT-1-IWyhZhU1hKKvWPddAJpdHRN2ECu08Ypo",
"token_type": "bearer",
"expires_in": 28800,
"refresh_token": "RT-1-cvHg23sAYRfu-1h8e57U9PSGK1qyL-mW"
}
1.2.2、获取用户信息
在已经获取到access_token令牌的情况下直接通过令牌就可以访问该接口,注意:安全要求高时,请求方式使用POST进行请求。
请求路径 | 请求方法 | 参数 | 描述 |
---|---|---|---|
/oauth2.0/profile | POST | access_token= |
获取用户信息 |
参数说明 :
参数名 | 是否必传 | 说明 |
---|---|---|
access_token | 是 | 访问令牌 |
返回值说明:
参数名 | 说明 |
---|---|
id | 用户名 |
attributes | 用户属性列表 |
返回数据示例(个人信息):
{
"attributes": {
"objectId": "5cf7849a3350660001256e28",
"SFLBDM": "02",
"TEL": "18819470607",
"XB": "男性",
"XH": "test003",
"XM": "傅光晨",
},
"id": "test003"
}
1.2.3、刷新令牌
当access_token令牌失效之后需要通过refresh_token刷新令牌,注意:安全要求高时,请求方式使用POST进行请求。
请求路径 | 请求方法 | 参数 | 描述 |
---|---|---|---|
/oauth2.0/accessToken | GET/POST | grant_type=refresh_token&client_id= |
使用刷新令牌获取访问令牌 |
入参字段说明:
参数名 | 是否必传 | 说明 |
---|---|---|
grant_type | 是 | 密码模式为password |
client_id | 是 | 应用账号 |
client_secret | 是 | 应用密钥 |
refresh_token | 是 | 刷新令牌 |
返回值说明:
参数名 | 说明 |
---|---|
access_token | 访问令牌 |
token_type | 令牌类型 |
expires_in | 令牌有效期 |
返回值示例数据:
{
"access_token": "AT-2-DiAnoWvJRJ-ZmJQZ5OGd3WxKGvg1qKwS",
"token_type": "bearer",
"expires_in": 28800
}
1.2.4 、查看访问令牌信息
请求路径 | 请求方法 | 认证参数(必传) | 请求参数(必传) | 描述 |
---|---|---|---|---|
/oauth2.0/introspect | POST | Basic Auth: HTTP头为Authorization, username= |
token= |
获取access_token信息 |
返回值说明:
参数名 | 说明 |
---|---|
active | 令牌是否有效,true,false |
sub | 使用者 |
scope | 令牌授权的scope |
iat | 令牌签发时间 |
exp | 令牌过期时间 |
tokenType | 令牌类型 |
iss | 签发者 |
grant_type | 令牌授权类型 |
返回示例数据:
{
"active": true,
"sub": "casuser",
"scope": "XXX",
"iat": 1539747458,
"exp": 28800,
"uniqueSecurityName": "casuser",
"tokenType": "bearer",
"iss": "http://localhost:8080/oidc",
"client_id": "ODYyMDg2NzE=",
"grant_type": "password"
}
2、客户端模式
2.1、原理
说明:与密码模式一样,只是传参不一致
2.2、接口说明
2.2.1、获取令牌接口
注意:安全要求高时,请求方式使用POST进行请求。
请求路径 | 请求方法 | 参数 | 描述 |
---|---|---|---|
/oauth2.0/accessToken | GET/POST | grant_type=client_credentials&client_id= |
客户端模式获取access_token |
入参字段说明:
参数名 | 是否必传 | 说明 |
---|---|---|
grant_type | 是 | 客户端模式,这里固定为client_credentials |
client_id | 是 | 应用账号 |
client_secret | 是 | 应用密钥 |
scope | 否 | 权限列表,以空格分隔,空为默认(以服务端为准) |
返回值说明:
参数名 | 说明 |
---|---|
access_token | 访问令牌 |
token_type | 令牌类型 |
expires_in | 令牌有效期 |
refresh_token | 刷新令牌 |
返回数据示例:
{
"access_token": "AT-1-IWyhZhU1hKKvWPddAJpdHRN2ECu08Ypo",
"token_type": "bearer",
"expires_in": 28800,
"refresh_token": "RT-1-cvHg23sAYRfu-1h8e57U9PSGK1qyL-mW"
}
注:密码模式和客户端模式类似,只有获取令牌传参不一致,其它地方相同
3、授权码模式
3.1、原理
说明:
1、 直接请求CAS服务端的authorize接口,传递一个回调地址
2、 CAS服务端处理成功之后回调第一步的回调地址,并将code携带过去
3、 客户端通过code请求CAS服务端的accessToken接口,并返回令牌信息
4、 接下来的操作需要携带令牌即可,如获取用户信息
3.2、接口说明
3.2.1、获取code
请求路径 | 请求方法 | 参数 | 描述 |
---|---|---|---|
/oauth2.0/authorize | GET | response_type=code&client_id= |
授权码模式认证用户 |
入参字段说明:
参数名 | 是否必传 | 说明 |
---|---|---|
response_type | 是 | 授权码模式,这里固定为code |
client_id | 是 | 应用账号 |
redirect_uri | 是 | 应用回调地址 |
scope | 否 | 权限列表,以空格分隔,空为默认(以服务端为准) |
返回值说明:
参数名 | 说明 |
---|---|
code | code参数在CALLBACK url里 |
3.2.2、通过code获取access_token
注意:安全要求高时,请求方式使用POST进行请求。
请求路径 | 请求方法 | 参数 | 描述 |
---|---|---|---|
/oauth2.0/accessToken | POST | grant_type=authorization_code&client_id= &redirect_uri=
|
授权码模式认证用户 |
入参字段说明:
参数名 | 是否必传 | 说明 |
---|---|---|
grant_type | 是 | 授权码模式,这里固定为authorization_code |
client_id | 是 | 应用账号 |
client_secret | 是 | 应用密钥 |
redirect_uri | 是 | 应用回调地址 |
code | 是 | code |
返回值说明:
参数名 | 说明 |
---|---|
access_token | 访问令牌 |
token_type | 令牌类型 |
expires_in | 令牌有效期 |
refresh_token | 刷新令牌 |
code | 上一步获取到的code |
二、java版实现
1、密码模式实现
可参考类OAuthPasswordController.java
1.1、登录
说明:向CAS服务端发送令牌请求,然后将请求到的令牌保存到session中,并设置令牌的失效时间,保存刷新令牌,以便令牌失效之后通过refresh_token获取令牌
//为了演示方便,这里使用get请求,登录一般使用post
@GetMapping("login")
@ResponseBody
public String accessToken(String username,String password,HttpServletRequest request, HttpServletResponse response){
//向CAS服务端请求地址
String url = "https://sid.rghall.com.cn/oauth2.0/accessToken";
Map<String,String> params = new HashMap<>();
//密码模式
params.put("grant_type","password");
//应用账号
params.put("client_id","casJava");
//用户名
params.put("username",username);
//密码
params.put("password",password);
//发送GET请求
String s = HttpClientUtils.getInstance().doPostRequest(url, null, params);
//解析json
JSONObject jsonObject = JSONObject.parseObject(s);
//获取token
String accessToken = jsonObject.getString("access_token");
//获取刷新令牌,如果令牌失效,则通过刷新令牌获取
String refreshToken = jsonObject.getString("refresh_token");
//令牌失效时间
String expiresIn = jsonObject.getString("expires_in");
System.out.println("access_token:" + accessToken);
System.out.println("refresh_token:" + refreshToken);
System.out.println("expires_in:" + expiresIn);
//获取session
HttpSession session = request.getSession();
//将accessToken保存到session中
session.setAttribute("accessToken",accessToken);
//为session设置失效时间
session.setMaxInactiveInterval(10);
//将refreshToken保存起来
this.refreshToken = refreshToken;
return s;
}
1.2、获取用户信息
说明:直接携带令牌访问,如果令牌已经失效,则需要通过refresh_token请求令牌
@GetMapping(value = "profile",produces="text/json;charset=utf-8")
@ResponseBody
public String profile(HttpServletRequest request, HttpServletResponse response){
//从session中获取token
Object accessToken = request.getSession().getAttribute("accessToken");
if(accessToken ==null){
//token已经失效,需要重新获取
String url = "https://sid.rghall.com.cn/oauth2.0/accessToken";
Map<String,String> map = new HashMap<>();
//刷新令牌模式
map.put("grant_type","refresh_token");
//应用账号
map.put("client_id","casJava");
//应用密钥
map.put("client_secret","89s4Iw9yh7AJms4C8FD6SN6j0PlgD8eF2arK_F4cAXeOBjHDo0aSi7p0DSt5cJB0");
//刷新令牌
map.put("refresh_token",refreshToken);
//发送请求
String s = HttpClientUtils.getInstance().doPostRequest(url, null, map);
//解析返回结果
JSONObject jsonObject = JSONObject.parseObject(s);
//获取令牌
accessToken = jsonObject.getString("access_token");
//获取令牌失效时间
String expiresIn = jsonObject.getString("expires_in");
HttpSession session = request.getSession();
//将token重新设置到session中
session.setAttribute("accessToken",accessToken);
//设置失效时间
session.setMaxInactiveInterval(Integer.parseInt(expiresIn));
}
String url = "https://sid.rghall.com.cn/oauth2.0/profile";
Map<String,String> params = new HashMap<>();
params.put("access_token",accessToken + "");
//获取个人信息
String s = HttpClientUtils.getInstance().doGetRequest(url, null, params);
return s;
}
1.3、登出
说明:将session置为无效,然后向CAS服务端发送登出请求即可
@GetMapping("logout")
@ResponseBody
public String logout(HttpServletRequest request, HttpServletResponse response){
//将session设置为无效
request.getSession().invalidate();
String url = "https://sid.rghall.com.cn/logout";
//向CAS服务端发送登出请求
String s = HttpClientUtils.getInstance().doGet(url,null);
return "logout success";
}
2、客户端模式实现
说明:客户端模式与密码模式雷同,这里只展示登录模块,其余模块与密码模式一样。
2.1、登录
@GetMapping("login")
@ResponseBody
public String accessToken(HttpServletRequest request, HttpServletResponse response){
//向CAS服务端请求地址
String url = "https://sid.rghall.com.cn/oauth2.0/accessToken";
Map<String,String> params = new HashMap<>();
//客户端模式
params.put("grant_type","client_credentials");
//应用账号
params.put("client_id","casJava");
//应用密钥
params.put("client_secret","89s4Iw9yh7AJms4C8FD6SN6j0PlgD8eF2arK_F4cAXeOBjHDo0aSi7p0DSt5cJB0");
//发送GET请求
String s = HttpClientUtils.getInstance().doGetRequest(url, null, params);
//解析json
JSONObject jsonObject = JSONObject.parseObject(s);
//获取token
String accessToken = jsonObject.getString("access_token");
//获取刷新令牌,如果令牌失效,则通过刷新令牌获取
String refreshToken = jsonObject.getString("refresh_token");
//令牌失效时间
String expiresIn = jsonObject.getString("expires_in");
System.out.println("access_token:" + accessToken);
System.out.println("refresh_token:" + refreshToken);
System.out.println("expires_in:" + expiresIn);
//获取session
HttpSession session = request.getSession();
//将accessToken保存到session中
session.setAttribute("accessToken",accessToken);
//为session设置失效时间
session.setMaxInactiveInterval(10);
//将refreshToken保存起来
this.refreshToken = refreshToken;
return s;
}
3、授权码模式
说明:先请求code,然后通过code请求access_token
3.1、获取授权码
@GetMapping("loginByCode")
@ResponseBody
public void accessToken(HttpServletRequest request, HttpServletResponse response){
//统一身份中心地址
String serverUrl = "https://sid.rghall.com.cn";
//身份中心分发的clientId
String client_id = "";
//回调地址,登录成功后会将code传递给该地址
String redirect_uri = "ip:port/receive";
StringBuilder url = new StringBuilder();
url.append(serverUrl).append("/oauth2.0/authorize");
url.append("?response_type=code&client_id=");
url.append(client_id);
url.append("&redirect_uri=");
url.append(getEncodeUrl(redirect_uri));
response.sendRedirect(url.toString());
}
private String getEncodeUrl(String url) throws UnsupportedEncodingException {
return URLEncoder.encode(url, StandardCharsets.UTF_8.toString());
}
3.2、获取access_token
@RequestMapping("receive")
public void receive(HttpServletRequest request, @RequestParam("code") String code){
//向CAS服务端请求地址
String url = "https://sid.rghall.com.cn/oauth2.0/accessToken";
Map<String,Object> params = new HashMap<>();
//客户端模式
params.put("grant_type","authorization_code");
//应用账号
params.put("client_id","casJava");
//应用密钥
params.put("client_secret","89s4Iw9yh7AJms4C8FD6SN6j0PlgD8eF2arK_F4cAXeOBjHDo0aSi7p0DSt5cJB0");
//应用回调地址
params.put("redirect_uri","ip:port/receive");
//发送GET请求
String s = HttpClientUtils.getInstance().doPost(url,null, params);
//解析json
JSONObject jsonObject = JSONObject.parseObject(s);
//获取token
String accessToken = jsonObject.getString("access_token");
//获取刷新令牌,如果令牌失效,则通过刷新令牌获取
String refreshToken = jsonObject.getString("refresh_token");
//令牌失效时间
String expiresIn = jsonObject.getString("expires_in");
System.out.println("access_token:" + accessToken);
System.out.println("refresh_token:" + refreshToken);
System.out.println("expires_in:" + expiresIn);
//获取session
HttpSession session = request.getSession();
//将accessToken保存到session中
session.setAttribute("accessToken",accessToken);
//为session设置失效时间
session.setMaxInactiveInterval(10);
//将refreshToken保存起来
this.refreshToken = refreshToken;
}
4、java附件
三、php版实现
请确保你的php 环境支持curl
1、密码模式实现
可参考附件oauth_login.php
1.1、登录
/** ------------------------------密码模式-------------------------*/
/**
* 请求获取access_token配置
*/
//获取令牌地址(需要配置)
$access_token_url = 'https://sid.rghall.com.cn/oauth2.0/accessToken';
//连接ID
$clientid = 'casJava';
//连接secret
$secret='89s4Iw9yh7AJms4C8FD6SN6j0PlgD8eF2arK_F4cAXeOBjHDo0aSi7p0DSt5cJB0';
//从表单中获取帐号密码
if(array_key_exists('username',$_GET) && array_key_exists('username',$_GET)){
//用户名
$username=$_GET['username'];
//用户密码
$password=$_GET['password'];
}else{
echo '请填写帐号密码';die;
}
//拼接请求令牌参数地址
$url = $access_token_url.'?grant_type=password&client_id='.$clientid.'&username='.$username.'&password='.$password;
//发起请求
$data = curl_get($url);
if($data == false){
echo '连接ID,帐号或密码错误';die;
}
//下面为获取到的令牌信息
//$data = [
// "access_token"=>"AT-889-7t8VjSjQx-PDBJvvXJzZTkkoG8zGMSth",//访问令牌
// "token_type"=>"bearer", //令牌类型
// "expires_in"=>28800, //令牌有效期
// "refresh_token"=>"RT-802-Xof-xF7CmaTbNyxVPTB-g3W8Q2AhaRFK"//刷新令牌
//];
//获取到令牌后存起来(可根据业务需要选择存储方式(redis,session,数据库,cookie等等))
//登录
setcookie('access_token',$data['access_token'],$data['expires_in']+time());
setcookie('expires_in',$data['expires_in']+time());
setcookie('refresh_token',$data['refresh_token']);
setcookie('token_type',$data['token_type']);
//登录成功跳转到获取用户信息地址
header('Location:/oauth_profile.php');
/**-------------------END------------------------------------*/
1.2、获取用户信息
可参考附件oauth_profile.php
说明:直接携带令牌访问,如果令牌已经失效,则需要通过refresh_token请求令牌
**
* 获取用户信息|刷新令牌|判断令牌是否有效配置
*/
//刷新令牌地址(需要配置)
$access_token_url = 'https://sid.rghall.com.cn/oauth2.0/accessToken';
//判断令牌地址(需要配置)
$check_token_url = 'https://sid.rghall.com.cn/oauth2.0/introspect';
//获取用户信息地址(需要配置)
$profile_url = 'https://sid.rghall.com.cn/oauth2.0/profile';
//连接ID(需配置)
$clientid = 'casJava';
//连接secret(需配置)
$secret='89s4Iw9yh7AJms4C8FD6SN6j0PlgD8eF2arK_F4cAXeOBjHDo0aSi7p0DSt5cJB0';
/**
* 获取用户信息
*/
//判断是否登录
if(isset($_COOKIE['access_token'])&&isset($_COOKIE['expires_in'])&&isset($_COOKIE['token_type']))
{
//获取令牌
$access_token = $_COOKIE['access_token'];
//获取令牌过期时间
$expires_in = $_COOKIE['expires_in'];
/**判断令牌是否有效*/
//添加头,在name和pass处填写对应账号密码
$arr_header[]= "application/x-www-form-urlencoded";
$arr_header[] = "Authorization: Basic ".base64_encode($clientid.":".$secret);
$post_data = "token=".$access_token;
$res = curl_post($check_token_url,$post_data, $arr_header);
if($res['active'] == false){
echo '令牌失效';die;
}
/**刷新令牌*/
//判断令牌过期时间(临近1小时过期时刷新一次)
if(time() >= $expires_in + 3600 && isset($_COOKIE['refresh_token'])){
//获取刷新令牌
$refresh_token = $_COOKIE['refresh_token'];
$url = $access_token_url.'?grant_type=refresh_token&client_id='.$clientid.'&client_secret='.$secret.'&refresh_token='.$refresh_token;
$new_token = curl_get($url);
if($new_token!=false){
//更新登录状态
setcookie('access_token',$refresh_token['access_token'],$refresh_token['expires_in']+time());
setcookie('expires_in',$refresh_token['expires_in']+time());
}
}
//拼接请求用户信息参数地址
$url = $profile_url.'?access_token='.$access_token;
$info = curl_get($url);
//返回用户信息
echo json_encode($info);die;
}else{
echo '请登录后操作.....';
}
1.3、登出
可参考附件oauth_logout.php
说明:直接将cookie置为无效,跳转服务端退出登录
<?php
/**------------------退出登录-------------*/
//清除授权令牌与刷新令牌
setcookie('access_token',$data['access_token'],0);
setcookie('refresh_token',$data['refresh_token'],0);
//跳转退出地址
header('Location:https://sso.rghall.com.cn/logout');
/**-------------------END-----------------*/
2、客户端模式实现
可参考附件oauth_login.php,
2.1、登录
/** --------------客户端模式 ---------------------------------*/
/**
* 请求获取access_token配置
*/
//获取令牌地址(需要配置)
$access_token_url = 'https://sid.rghall.com.cn/oauth2.0/accessToken';
//连接ID
$clientid = 'casJava';
//连接secret
$secret='89s4Iw9yh7AJms4C8FD6SN6j0PlgD8eF2arK_F4cAXeOBjHDo0aSi7p0DSt5cJB0';
//拼接请求令牌参数地址
$url = $access_token_url.'?grant_type=client_credentials&client_id='.$clientid.'&client_secret='.$secret;
//发起请求
$data = curl_get($url);
if(empty($data)){
echo '连接ID或密钥错误';die;
}
//下面为获取到的令牌信息
//$data = [
// "access_token"=>"AT-889-7t8VjSjQx-PDBJvvXJzZTkkoG8zGMSth",//访问令牌
// "token_type"=>"bearer", //令牌类型
// "expires_in"=>28800, //令牌有效期
// "refresh_token"=>"RT-802-Xof-xF7CmaTbNyxVPTB-g3W8Q2AhaRFK"//刷新令牌
//];
//获取到令牌后存起来(可根据业务需要选择存储方式(redis,session,数据库,cookie等等))
//登录
setcookie('access_token',$data['access_token'],$data['expires_in']+time());
setcookie('expires_in',$data['expires_in']+time());
setcookie('token_type',$data['token_type']);
//登录成功跳转到获取用户信息地址
header('Location:/oauth_profile.php');
//
/** --------------------END------------------------*/
2.2、获取应用信息
请参考1.2
3、授权码模式
说明:先请求code,然后通过code请求access_token,可参考附件oauth_login.php,
3.1、获取授权码
//拼接跳转认证中心地址
$jump_to = $authorize_token_url.'?response_type=code&client_id='.$clientid.'&&redirect_uri=http://'.$_SERVER['SERVER_NAME'].'/oauth_login.php';
header('Location:'.$jump_to);
3.2、获取access_token
/** ------------------------------授权码模式 ---------------------------------*/
/**
* 请求获取access_token配置
*/
//跳转到认证中心地址(需要配置)
$authorize_token_url = 'https://sid.rghall.com.cn/oauth2.0/authorize';
//获取令牌地址(需要配置)
$access_token_url = 'https://sid.rghall.com.cn/oauth2.0/accessToken';
//连接ID(需要配置)
$clientid = 'casJava';
//连接secret(需要配置)
$secret='89s4Iw9yh7AJms4C8FD6SN6j0PlgD8eF2arK_F4cAXeOBjHDo0aSi7p0DSt5cJB0';
if(isset($_GET['code'])){
//拼接请求令牌参数地址
$url = $access_token_url.'?grant_type=authorization_code&client_id='.$clientid.'&client_secret='.$secret.'&redirect_uri=http://'.$_SERVER['SERVER_NAME'].'/oauth_login.php&code='.$_GET['code'];
//发起请求
$data = curl_get($url);
if(empty($data)){
echo 'code不正确';die;
}
//下面为获取到的令牌信息
//$data = [
//"access_token"=>"AT-889-7t8VjSjQx-PDBJvvXJzZTkkoG8zGMSth",//访问令牌
//"token_type"=>"bearer", //令牌类型
//"expires_in"=>28800, //令牌有效期
//"refresh_token"=>"RT-802-Xof-xF7CmaTbNyxVPTB-g3W8Q2AhaRFK"//刷新令牌
//];
//获取到令牌后存起来(可根据业务需要选择存储方式(redis,session,数据库,cookie等等))
//登录
setcookie('access_token',$data['access_token'],$data['expires_in']+time());
setcookie('expires_in',$data['expires_in']+time());
setcookie('refresh_token',$data['refresh_token']);
setcookie('token_type',$data['token_type']);
//登录成功跳转到获取用户信息地址
header('Location:/oauth_profile.php');
}else{
//拼接跳转认证中心地址
$jump_to = $authorize_token_url.'?response_type=code&client_id='.$clientid.'&&redirect_uri=http://'.$_SERVER['SERVER_NAME'].'/oauth_login.php';
header('Location:'.$jump_to);
}
4、php发起请求的方法
以下是两种方式POST和GET(请查看oauth_profile.php文件)
4.1、 GET
/**
* 发起请求方法(get)
*/
function curl_get($url){
$header = array(
'Accept: application/json',
);
$curl = curl_init();
//设置抓取的url
curl_setopt($curl, CURLOPT_URL, $url);
//设置头文件的信息作为数据流输出
curl_setopt($curl, CURLOPT_HEADER, 0);
// 超时设置,以秒为单位
curl_setopt($curl, CURLOPT_TIMEOUT, 1);
// 超时设置,以毫秒为单位
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
// 设置请求头
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
//设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
//执行命令
$data = curl_exec($curl);
return json_decode(htmlspecialchars_decode($data), true);
}
4.2、POST
/**
* 发起请求方法(post)
*/
function curl_post($url,$data = null,$arr_header = null){
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
// curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
// curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
if (!empty($data)){
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
if(!empty($arr_header)){
curl_setopt($curl, CURLOPT_HTTPHEADER, $arr_header);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
unset($curl);
return json_decode($output,true);
}
5、php附件
四、.net版实现
1、密码模式实现
可参考Mode_Password.aspx
1.1、登录
说明:向CAS服务端发送令牌请求,然后将请求到的令牌保存到session中,并设置令牌的失效时间,保存刷新令牌,以便令牌失效之后通过refresh_token获取令牌
//获取令牌地址
string targetURL = "https://sid.rghall.com.cn/oauth2.0/accessToken";
//参数
string clientId = "casJava";
string grant_type = "password";
string userName = TxtUserName.Text;// "test003";
string password = TxtPassword.Text;// "123456";
string postDataStr = string.Format(
"grant_type={0}&client_id={1}&username={2}&password={3}",
Uri.EscapeDataString(grant_type),
Uri.EscapeDataString(clientId),
Uri.EscapeDataString(userName),
Uri.EscapeDataString(password)
);
targetURL = targetURL + "?"+ postDataStr;
//获取令牌请求
HttpWebResponse response = HttpWebResponseUtility.CreateGetHttpResponse(targetURL, null, null, null);
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8);
string retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
response.Close();
//返回Json
resultDiv.InnerHtml = retString;
LoginResult tk = JsonJavaScriptSerializer.FromJSON<LoginResult>(retString);
//令牌放入Session
Session["access_token"] = tk.access_token;
Session["refresh_token"] = tk.refresh_token;
1.2、获取用户信息
说明:直接携带令牌访问,如果令牌已经失效,则需要通过refresh_token请求令牌
string access_token = Session["access_token"].ToString();
if (string.IsNullOrEmpty(access_token))//令牌是否失效
{
string targetURL = "https://sid.rghall.com.cn/oauth2.0/accessToken";//刷新令牌请求地址
//请求参数
string grant_type = "refresh_token";
string clientId = "casJava";
string client_secret = "89s4Iw9yh7AJms4C8FD6SN6j0PlgD8eF2arK_F4cAXeOBjHDo0aSi7p0DSt5cJB0";
string refresh_token = Session["refresh_token"].ToString(); ;
string postDataStr = string.Format(
"grant_type={0}&client_id={1}&client_secret={2}&refresh_token={3}",
Uri.EscapeDataString(grant_type),
Uri.EscapeDataString(clientId),
Uri.EscapeDataString(client_secret),
Uri.EscapeDataString(refresh_token)
);
targetURL = targetURL + "?" + postDataStr;
//刷新令牌请求
HttpWebResponse response = HttpWebResponseUtility.CreateGetHttpResponse(targetURL, null, null, null);
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8);
string retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
response.Close();
//解析Json
LoginResult tk = JsonJavaScriptSerializer.FromJSON<LoginResult>(retString);
//重置Token令牌
Session["access_token"] = tk.access_token;
}
String url = "https://sid.rghall.com.cn/oauth2.0/profile";//获取个人信息地址
string acc_token = Session["access_token"].ToString(); ;
string postDataStr0 = string.Format(
"access_token={0}",
Uri.EscapeDataString(acc_token)
);
url = url + "?" + postDataStr0;
//获取个人信息
HttpWebResponse response0 = HttpWebResponseUtility.CreateGetHttpResponse(url, null, null, null);
Stream myResponseStream0 = response0.GetResponseStream();
StreamReader myStreamReader0 = new StreamReader(myResponseStream0, Encoding.UTF8);
string retString0 = myStreamReader0.ReadToEnd();
myStreamReader0.Close();
response0.Close();
//个人信息Json
resultDiv.InnerHtml = retString0;
1.3、登出sid.rghall.com.cn
说明:将session置为无效,然后向CAS服务端发送登出请求即可
String url = "https:///logout";
Session["access_token"] = null;//本地Session清空
//向CAS服务端发送登出请求
HttpWebResponse response0 = HttpWebResponseUtility.CreateGetHttpResponse(url, null, null, null);
Stream myResponseStream0 = response0.GetResponseStream();
StreamReader myStreamReader0 = new StreamReader(myResponseStream0, Encoding.UTF8);
string retString0 = myStreamReader0.ReadToEnd();
myStreamReader0.Close();
response0.Close();
resultDiv.InnerHtml = "logout success:"+ retString0;
2、客户端模式实现
说明:客户端模式与密码模式雷同,这里只展示登录模块,其余模块与密码模式一样。参见:Mode_Client.aspx
2.1、登录
string targetURL = "https://sid.rghall.com.cn/oauth2.0/accessToken";
//参数
string clientId = "casJava";//应用ID
string grant_type = "client_credentials";//客户端的模式
string client_secret = "89s4Iw9yh7AJms4C8FD6SN6j0PlgD8eF2arK_F4cAXeOBjHDo0aSi7p0DSt5cJB0";////应用密钥
string postDataStr = string.Format(
"grant_type={0}&client_id={1}&client_secret={2}",
Uri.EscapeDataString(grant_type),
Uri.EscapeDataString(clientId),
Uri.EscapeDataString(client_secret)
);
targetURL = targetURL + "?" + postDataStr;
//获取令牌请求
HttpWebResponse response = HttpWebResponseUtility.CreateGetHttpResponse(targetURL, null, null, null);
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8);
string retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
response.Close();
//返回Json
resultDiv.InnerHtml = retString;
//Json解析
LoginResult tk = JsonJavaScriptSerializer.FromJSON<LoginResult>(retString);
//令牌放入Session
Session["access_token"] = tk.access_token;
Session["refresh_token"] = tk.refresh_token;
3、授权码模式
说明:先请求code,然后通过code请求access_token。参见:Mode_AuthCode.aspx
3.1、获取授权码
//获取授权地址
string targetURL = "https://sid.rghall.com.cn/oauth2.0/authorize";
//参数
string clientId = "casJava"; //应用账号
string response_type = "code"; //授权码模式
string redirect_uri = "ip:port/receive";//回调地址,会将code携带到该地址
string postDataStr = string.Format(
"response_type={0}&client_id={1}&redirect_uri={2}",
Uri.EscapeDataString(response_type),
Uri.EscapeDataString(clientId),
Uri.EscapeDataString(redirect_uri)
);
targetURL = targetURL + "?" + postDataStr;
//发送请求
HttpWebResponse response = HttpWebResponseUtility.CreateGetHttpResponse(targetURL, null, null, null);
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8);
string retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
response.Close();
//返回Json
resultDiv.InnerHtml = "login success " + retString;
3.2、获取access_token
//向CAS服务端请求地址
string targetURL = "https://sid.rghall.com.cn/oauth2.0/accessToken";
//参数
string clientId = "casJava";//应用账号
string grant_type = "authorization_code";//授权码模式
string client_secret = "89s4Iw9yh7AJms4C8FD6SN6j0PlgD8eF2arK_F4cAXeOBjHDo0aSi7p0DSt5cJB0"; //应用密钥
string redirect_uri = "ip:port/receive"; //应用回调地址
string postDataStr = string.Format(
"grant_type={0}&client_id={1}&client_secret={2}&redirect_uri={3}",
Uri.EscapeDataString(grant_type),
Uri.EscapeDataString(clientId),
Uri.EscapeDataString(client_secret),
Uri.EscapeDataString(redirect_uri)
);
targetURL = targetURL + "?" + postDataStr;
//发送GET请求
HttpWebResponse response = HttpWebResponseUtility.CreateGetHttpResponse(targetURL, null, null, null);
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8);
string retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
response.Close();
//返回Json
resultDiv.InnerHtml = retString;
//Json解析
LoginResult tk = JsonJavaScriptSerializer.FromJSON<LoginResult>(retString);
//令牌放入Session
Session["access_token"] = tk.access_token;
Session["refresh_token"] = tk.refresh_token;
4、.net的JSon转化
public static class JsonJavaScriptSerializer//序列化Helper
{
//Json字符串转内存对象
public static T FromJSON<T>(string jsonString)
{
JavaScriptSerializer json = new JavaScriptSerializer();
return json.Deserialize<T>(jsonString);
}
// 内存对象转换为json字符串
public static string ToJSON(object obj)
{
StringBuilder sb = new StringBuilder();
JavaScriptSerializer json = new JavaScriptSerializer();
json.Serialize(obj, sb);
return sb.ToString();
}
}
5、.net的Get请求
/// <summary>
/// 创建GET方式的HTTP请求
/// </summary>
/// <param name="url">请求的URL</param>
/// <param name="timeout">请求的超时时间</param>
/// <param name="userAgent">请求的客户端浏览器信息,可以为空</param>
/// <param name="cookies">随同HTTP请求发送的Cookie信息,如果不需要身份验证可以为空</param>
/// <returns></returns>
public static HttpWebResponse CreateGetHttpResponse(string url, int? timeout, string userAgent, CookieCollection cookies)
{
if (string.IsNullOrEmpty(url))
{
throw new ArgumentNullException("url");
}
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "GET";
request.UserAgent = DefaultUserAgent;
if (!string.IsNullOrEmpty(userAgent))
{
request.UserAgent = userAgent;
}
if (timeout.HasValue)
{
request.Timeout = timeout.Value;
}
if (cookies != null)
{
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add(cookies);
}
return request.GetResponse() as HttpWebResponse;
}
6、.net附件
测试
1、在浏览器上输入:http://ip:port/login?username=test003&password=123456 即可获取token,获取到token之后将其保存到session中,下次请求直接携带token即可。
获取个人信息,在浏览器上直接输入: http://ip:port/profile
登出,在浏览器上直接输入: http://ip:port/logout