OAuth2.0认证demo示例

Oauth2.0接口说明

java版实现

php版实现

.net版实现

一、Oauth2.0接口说明

说明:

​ 接入前请确保已在SourceID中开通相关用户或应用及权限

特点及应用场景:

​ 1.授权码模式:安全性高,使用率高,流程复杂。要求第三方应用必须有服务器。对安全性要求较高,web项目中一般使用授权码模式 ​ 2.密码模式:需要输入账号密码,极度不安全,需要高度信任第三方应用 ​ 适用于其他授权模式都无法采用的情况;原生APP可以使用,web不建议使用 ​ 3. 客户端模式:授权维度为应用维度,而不是用户维度。因此有可能多个用户共用一个Token的情况。适用于应用维度的共享资源。适用于服务器之间交互,不需要用户参与。

1、密码模式

1.1、原理说明

img

说明:

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=&username=USERNAME&password=PASSWORD 密码模式

入参字段说明:

参数名 是否必传 说明
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=&client_secret=&refresh_token= 使用刷新令牌获取访问令牌

入参字段说明:

参数名 是否必传 说明
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= Password= 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、原理

img

说明:与密码模式一样,只是传参不一致

2.2、接口说明

2.2.1、获取令牌接口

注意:安全要求高时,请求方式使用POST进行请求。

请求路径 请求方法 参数 描述
/oauth2.0/accessToken GET/POST grant_type=client_credentials&client_id=&client_secret= 客户端模式获取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、原理

img

说明:

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=&redirect_uri= 授权码模式认证用户

入参字段说明:

参数名 是否必传 说明
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=&client_secret=
&redirect_uri=&code=
授权码模式认证用户

入参字段说明:

参数名 是否必传 说明
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附件

cas-oauth-demo

三、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附件

php-oauth-demo

四、.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附件

.net-oauth-demo

测试

1、在浏览器上输入:http://ip:port/login?username=test003&password=123456 即可获取token,获取到token之后将其保存到session中,下次请求直接携带token即可。

img

获取个人信息,在浏览器上直接输入: http://ip:port/profile

img

登出,在浏览器上直接输入: http://ip:port/logout

©2020 锐捷网络股份有限公司 all right reserved,powered by Gitbook该文章修订时间: 2025-02-18 14:26:09

results matching ""

    No results matching ""