Oauth2协议 通过js和ajax获取token及刷新token

基于Oauth2.0协议授权码模式的认证流程

授权码模式工作流程:

  1. 浏览器访问某个受保护的资源,客户端自动将网页重定向到认证服务器(/oauth/authorize),携带clientid等信息
  2. 用户选择是否给予客户端授权(可自动授权)
  3. 认证服务器将浏览器重定向到”重定向URI”(redirection URI),同时附上一个授权码
  4. 浏览器拿到授权码,附上早先的”重定向URI”,向认证服务器申请令牌(/oauth/token)
  5. 认证服务器核对了授权码和重定向URI,向客户端发送访问令牌(access token)和更新令牌(refresh token)

步骤1中,客户端申请认证的URI,包含以下参数:

  • response_type:表示授权类型,必选项,此处的值固定为”code”
  • client_id:表示客户端的ID,必选项
  • redirect_uri:表示重定向URI,可选项
  • scope:表示申请的权限范围,可选项
  • state:一般随机生成,标识客户端的当前状态,认证服务器会原样返回这个值,

纯前端项目中获取token

通过JS ajax拦截器获取token及刷新token示例,适用于前后端分离项目中前端的授权。

auth.js

const FULL_CHARTER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopgrstuvwxyz';
const oauth_server='http://localhost:9000/server';
const redirect_uri='http://localhost:8002/client-front/';
const client_id='demo';
const client_secret='demo';
const token_storage = localStorage;//sessionStorage


function ajaxSetup() {
    $.ajaxSetup({
        timeout : 30000,
        beforeSend : function(xhr) {
            if(this.url.endsWith('/oauth/token')){
                return true;
            }
            if (getAuth() == null){
                fetchToken();
            }
            var auth = getAuth();
            if(auth != null){
                xhr.setRequestHeader("Authorization", auth.token_type + ' ' + auth.access_token);
            } else {
                return false;
            }
            return true;
        },
        complete : function(xhr, ts) {
            if (xhr.status == 401 && xhr.responseJSON.error =='invalid_token') {
               refreshToken();
            }
        }
    });
}

function getAuth(){
    let auth = token_storage.getItem('auth');
    return JSON.parse(auth);
}

function saveAuth(sResponse){
    token_storage.setItem("auth", JSON.stringify(sResponse));
}

function clearAuth(){
    token_storage.removeItem('auth');
}

function logout(){
    token_storage.removeItem('auth');
    window.location.href = oauth_server+"/logout?redirect_uri="+redirect_uri;
}

function getCode(){
var state='';
for (var a=0;a<6;a++){
    state+=FULL_CHARTER[Math.floor(Math.random() * 52)];
}
var url = oauth_server+"/oauth/authorize?client_id="+client_id+"&client_secret="+client_secret+
          "&response_type=code&state="+state+"&redirect_uri="+redirect_uri;
 window.location = url;
 //window.open(url);
}

function fetchToken(){
    let url = window.location.toString();
    if(!url.includes('code')){
        getCode();
    }
    if(url.includes('code')) {
      let code=url.substr(url.indexOf('code=')+5,6);
      let state=url.substr(url.indexOf('state=')+6,6);

        var data={
        'code':code,
        'state':state,
        'grant_type':'authorization_code',
        'redirect_uri':redirect_uri
        };
    $.ajax({
       url: oauth_server+"/oauth/token",
       type:"post",
       data:data,
       async: false,
       contentType: 'application/x-www-form-urlencoded',
       beforeSend:function(xhr){
             xhr.setRequestHeader("Authorization", 'Basic ' + Base64.encode(client_id+':'+client_secret));
        },
       success: function (sResponse) {
        saveAuth(sResponse);
        console.log('fetch_token ok: ' + sResponse.access_token+'  expires_in:'+sResponse.expires_in);
        //window.location.href = redirect_uri;
       },
       error:function(a,b,c){
        console.log(a, b, c);
       }
    });
    }
}

function refreshToken(){
    var auth = getAuth();
    var data={
            'client_id': client_id,
            'client_secret': client_secret,
            'grant_type':'refresh_token',
            'refresh_token':auth.refresh_token
            };
        $.ajax({
           url: oauth_server+"/oauth/token",
           type:"post",
           data:data,
           async: false,
           contentType: 'application/x-www-form-urlencoded',
           success: function (sResponse) {
            saveAuth(sResponse);
            console.log('refresh_token ok: ' + sResponse.access_token+'  expires_in:'+sResponse.expires_in);
           },
           error:function(a,b,c){
            if (a.status==400 && a.responseJSON.error=='invalid_grant'){
                console.log('refresh token invalid');
                clearAuth();
            }
           }
        });
}

function checkToken(){
            $.ajax({
               url: oauth_server+"/oauth/check_token",
               type:"get",
               async: false,
               data: {'token': getAuth().access_token},
               contentType: 'application/x-www-form-urlencoded',
               success: function (sResponse) {
                console.log('check_token : ' + sResponse);
               },
               error:function(a,b,c){
                console.log(a.responseJSON);
               }
            });
}

function getServerdata(){
    $.get(oauth_server+"/msg", function(data) {
            $("#user").html(data);
          });
}


$(function() {
    ajaxSetup();
});

其中使用了base64.js.

界面如下,点击GET Data按钮将发送/msg请求到授权服务器去获取一段文本:

文本获取成功后浏览器所有请求如下:

首先访问/msg,返回401无权限,然后浏览器转到/oauth/authorize去获取code,然后授权服务器返回302重定向到授权登录页,用户填写用户名密码后post到/login, 然后授权服务器重定向到rediret_url,末尾拼接了code,取出code,post发送/oauth/token请求,授权服务器返回token信息如下,并保存在LocalStorage中,如图所示:

获取token后/msg请求中携带了token信息,bearer为token类型:

由于是跨域请求数据,所以先发送的是OPTIONS请求,需要服务器支持跨域:

刷新token:

当服务器返回401,并且responseMsg为invalid_token时表示token已失效,post以下信息到/oauth/token,刷新token的失效时间

checktoken:需要服务器permitAll()该请求

登出:

在授权服务器中可查看所有生成的token: 

 

 

 

 

--------------------------END--------------------------

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot项目中,可以通过OAuth2来获取Token。具体步骤如下: 1. 当第三方同意授权后,会调用发送回执给我们的服务器。服务器会拿到一个中间授信凭据,然后进行认证,目的是为了获取Token。这个认证的逻辑由负责\[1\]。 2. 在获取Token的过程中,可以使用UsernamePasswordAuthenticationToken类来进行认证。可以通过创建一个UsernamePasswordAuthenticationToken对象,传入用户名和密码来进行认证\[2\]。 3. 在OAuth 2.0中,可以使用Authorization Code Grant模式来实现认证。这个模式的具体实现可以参考Spring Security的相关文档和示例代码\[3\]。 总结起来,通过OAuth2获取Token的步骤包括第三方同意授权、服务器进行认证获取中间授信凭据,然后使用UsernamePasswordAuthenticationToken类进行认证,最后根据具体的OAuth 2.0授权模式来获取Token。 #### 引用[.reference_title] - *1* *3* [Spring Security 实战干货:OAuth2登录获取Token的核心逻辑](https://blog.csdn.net/yetaodiao/article/details/127371959)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [基于SpringBoot整合oauth2实现token认证](https://blog.csdn.net/weixin_42363231/article/details/114121241)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值