本文章大致是如下流程:
创建两个.NETFramework工程,JWT加密,解密,实现单点登录验证流程。
**
废话不多说,实战帮助人
**
- 创建ASP.NET Web Application(.NETFramework) 工程
在很多类型的工程都可以引用JWT,本文章引用的是比较常用的ASP.NET Web Application (.NETFramework),然后选择创建空项目,check上MVC和WebAPI
- 项目1化名为T1,项目1化名为T2(T2待会再说)
- NuGet 添加 JWT 组件
天给大家看看,我创建后的目录结构:
根据目录结构,可以很清晰看到我自己添加的类文件,我回一一把代码发给大家,仅供参考
TokenController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using THC.Models;
using System.Text;
namespace THC.Controllers
{
[RoutePrefix("api/Token")]
public class TokenController : ApiController
{
/// <summary>
/// 登录
/// </summary>
/// <param name="loginRequest"></param>
/// <returns></returns>
[HttpPost]
[Route("Login")]
public TokenInfo Login([FromBody] LoginRequest loginRequest)
{
TokenInfo tokenInfo = new TokenInfo();//需要返回的口令信息
if (loginRequest != null)
{
string userName = loginRequest.UserName;
string passWord = loginRequest.Password;
string userEmail = "test@thc.net.cn";
bool isAdmin = (userName == "bd")?true:false;
//模拟数据库数据,真正的数据应该从数据库读取
//身份验证信息
AuthInfo authInfo = new AuthInfo { Name=userName,Email=userEmail ,IsAdmin= isAdmin, ExpiryDateTime = DateTime.Now.AddHours(2) };
const string secretKey = "THC";//口令加密秘钥
try
{
byte[] key = Encoding.UTF8.GetBytes(secretKey);
IJwtAlgorithm algorithm = new HMACSHA256Algorithm();//加密方式
IJsonSerializer serializer = new JsonNetSerializer();//序列化Json
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();//base64加解密
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);//JWT编码
var token = encoder.Encode(authInfo, key);//生成令牌
//口令信息
tokenInfo.Success = true;
tokenInfo.Token = token;
tokenInfo.Message = "OK";
}
catch(Exception ex)
{
tokenInfo.Success = false;
tokenInfo.Message = ex.Message.ToString();
}
}
else
{
tokenInfo.Success = false;
tokenInfo.Message = "用户信息为空";
}
return tokenInfo;
}
}
}
BondsController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using THC.Filter;
using THC.Models;
using Newtonsoft.Json;
namespace THC.Controllers
{
[RoutePrefix("api/bonds")]
[ApiAuthorize]
public class BondsController : ApiController
{
/// <summary>
/// 获取用户信息
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("ReturnBonds")]
public BondAttr ReturnBonds()
{
BondAttr bondInfo = new BondAttr
{
Cusip = "3136ABZ63",
Desc = "FNR 13-11 AP",
Cpn = 0.015,
TrancheType = "NTL/PAC/AD,INV/IO",
CpnType = "InverseFloater",
Formula = 6.05,
WAM = 300,
Age = 55,
OFSize=1116000,
CFSize = 232650,
Price=91.85,
WAL=3.95,
Yield=0.00216,
Duration=3.2
};
return bondInfo;
}
}
}
ApiAuthorizeAttribute.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using JWT;
using JWT.Serializers;
using JWT.Algorithms;
using THC.Models;
using System.Text;
namespace THC.Filter
{
/// <summary>
/// 身份认证拦截器
/// </summary>
public class ApiAuthorizeAttribute: AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext actionContext)
{
//前端请求api时会将token存放在名为"auth"的请求头中
var authHeader = from t in actionContext.Request.Headers where t.Key == "auth" select t.Value.FirstOrDefault();
if (authHeader != null)
{
const string secretKey = "THC";//加密秘钥
string token = authHeader.FirstOrDefault();//获取token
if (!string.IsNullOrEmpty(token))
{
try
{
byte[] key = Encoding.UTF8.GetBytes(secretKey);
IJsonSerializer serializer = new JsonNetSerializer();
IDateTimeProvider provider = new UtcDateTimeProvider();
IJwtValidator validator = new JwtValidator(serializer, provider);
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
var algorithm = new HMACSHA256Algorithm();
IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);
//解密
var json = decoder.DecodeToObject<AuthInfo>(token, key, verify: true);
if (json != null)
{
//判断口令过期时间
if (json.ExpiryDateTime < DateTime.Now)
{
return false;
}
actionContext.RequestContext.RouteData.Values.Add("auth", json);
return true;
}
return false;
}
catch (Exception ex)
{
return false;
}
}
}
return false;
}
}
}
AuthInfo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace THC.Models
{
/// <summary>
/// 身份验证信息 模拟JWT的payload
/// </summary>
public class AuthInfo
{
/// <summary>
/// name
/// </summary>
public string Name { get; set; }
/// <summary>
/// Email
/// </summary>
public string Email { get; set; }
/// <summary>
/// role
/// </summary>
public List<string> Roles { get; set; }
/// <summary>
/// is admin
/// </summary>
public bool IsAdmin { get; set; }
/// <summary>
/// expiry date
/// </summary>
public DateTime? ExpiryDateTime { get; set; }
}
}
BondAttr.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace THC.Models
{
public class BondAttr
{
public string Cusip { get; set; }
public string Desc { get; set; }
public double Cpn { get; set; }
public string TrancheType { get; set; }
public string CpnType { get; set; }
public double Formula { get; set; }
public double WAM { get; set; }
public double Age { get; set; }
public double OFSize { get; set; }
public double CFSize { get; set; }
public double Price { get; set; }
public double WAL { get; set; }
public double Yield { get; set; }
public double Duration { get; set; }
}
}
LoginRequest.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace THC.Models
{
/// <summary>
/// 登录用户信息
/// </summary>
public class LoginRequest
{
/// <summary>
/// user
/// </summary>
public string UserName { get; set; }
/// <summary>
/// ps
/// </summary>
public string Password { get; set; }
/// <summary>
/// email
/// </summary>
public string UserEmail { get; set; }
}
}
TokenInfo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace THC.Models
{
/// <summary>
/// 生成的口令信息
/// </summary>
public class TokenInfo
{
/// <summary>
/// 是否成功
/// </summary>
public bool Success { get; set; }
/// <summary>
/// 令牌
/// </summary>
public string Token { get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string Message { get; set; }
}
}
web.config
注释掉OPTIONSVerbHandler,然后加上下面这段,支持跨域
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
https://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.7.2" />
<httpRuntime targetFramework="4.7.2" />
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" />
</namespaces>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<!--<remove name="OPTIONSVerbHandler" />-->
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headres" value="*"/>
<add name="Access-Control-Allow-Methods" value="*"/>
</customHeaders>
</httpProtocol>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\"Web\" /optionInfer+" />
</compilers>
</system.codedom>
</configuration>
至此T1项目已经完成,T2项目和T1类似,创建工程和下载JWT组件一样的,下面是T2目录
BondsController.cs
using System;
using System.Web;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.SessionState;
using MBSSource.Filter;
using MBSSource.Models;
using Newtonsoft.Json;
using static MBSSource.APIUserEnvironment;
namespace MBSSource.Controllers
{
[RoutePrefix("api/bonds")]
[ApiAuthorize]
public class BondsController : ApiController
{
/// <summary>
/// 获取用户信息
/// </summary>
/// <returns></returns>
[HttpPost]
[Route("BidBond")]
public BondBidAttr BidBond(BondBidAttr bid)
{
return bid;
}
/*
public ReturnBond BidBond(BondBidAttr bid)
{
ReturnBond rb = new ReturnBond();
try
{
AuthInfo tinfo = GetCurrentUser(); //(AuthInfo)HttpContext.Current.Session["tokenInfo"];
rb.BidBond = bid; rb.User = tinfo;
}
catch (Exception)
{
return null;
}
return rb;
}
*/
}
}
TokenController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using MBSSource.Models;
using System.Text;
namespace MBSSource.Controllers
{
[RoutePrefix("api/Token")]
public class TokenController : ApiController
{
/// <summary>
/// 登录
/// </summary>
/// <param name="loginRequest"></param>
/// <returns></returns>
[HttpPost]
[Route("Login")]
public TokenInfo Login([FromBody] LoginRequest loginRequest)
{
TokenInfo tokenInfo = new TokenInfo();//需要返回的口令信息
if (loginRequest != null)
{
string userName = loginRequest.UserName;
string passWord = loginRequest.Password;
string userEmail = "test@thc.net.cn";
bool isAdmin = (userName == "bd")?true:false;
//模拟数据库数据,真正的数据应该从数据库读取
//身份验证信息
AuthInfo authInfo = new AuthInfo { Name=userName,Email=userEmail, IsAdmin = isAdmin, ExpiryDateTime = DateTime.Now.AddHours(2) };
const string secretKey = "THC";//口令加密秘钥
try
{
byte[] key = Encoding.UTF8.GetBytes(secretKey);
IJwtAlgorithm algorithm = new HMACSHA256Algorithm();//加密方式
IJsonSerializer serializer = new JsonNetSerializer();//序列化Json
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();//base64加解密
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);//JWT编码
var token = encoder.Encode(authInfo, key);//生成令牌
//口令信息
tokenInfo.Success = true;
tokenInfo.Token = token;
tokenInfo.Message = "OK";
}
catch(Exception ex)
{
tokenInfo.Success = false;
tokenInfo.Message = ex.Message.ToString();
}
}
else
{
tokenInfo.Success = false;
tokenInfo.Message = "用户信息为空";
}
return tokenInfo;
}
}
}
ApiAuthorizeAttribute.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.SessionState;
using JWT;
using JWT.Serializers;
using JWT.Algorithms;
using MBSSource.Models;
using System.Text;
using Newtonsoft.Json;
namespace MBSSource.Filter
{
/// <summary>
/// 身份认证拦截器
/// </summary>
public class ApiAuthorizeAttribute: AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext actionContext)
{
//前端请求api时会将token存放在名为"auth"的请求头中
var authHeader = from t in actionContext.Request.Headers where t.Key == "auth" select t.Value.FirstOrDefault();
if (authHeader != null)
{
const string secretKey = "THC";//加密秘钥
string token = authHeader.FirstOrDefault();//获取token
if (!string.IsNullOrEmpty(token))
{
try
{
AuthInfo tokenInfo = ValidateJwtToken(token, secretKey);
if (tokenInfo != null) {
if (tokenInfo.ExpiryDateTime < DateTime.Now)
{
return false;
}
HttpContext.Current.Session["tokenInfo"] = tokenInfo;
//HttpContext.Current.Session["tokenInfo"] = tokenInfo;// JsonConvert.SerializeObject(tokenInfo);
actionContext.RequestContext.RouteData.Values.Add("auth", tokenInfo);
return true;
}
return false;
}
catch (Exception ex)
{
return false;
}
}
}
return false;
}
public static AuthInfo ValidateJwtToken(string token, string secret) {
try {
byte[] key = Encoding.UTF8.GetBytes(secret);
IJsonSerializer serializer = new JsonNetSerializer();
IDateTimeProvider provider = new UtcDateTimeProvider();
IJwtValidator validator = new JwtValidator(serializer, provider);
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
var algorithm = new HMACSHA256Algorithm();
IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);
//解密
var json = decoder.DecodeToObject<AuthInfo>(token, key, verify: true);
if (json != null)
{
//判断口令过期时间
if (json.ExpiryDateTime < DateTime.Now)
{
return null;
}
return json;
}
} catch (Exception) {
return null;
}
return null;
}
}
}
AuthInfo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace THC.Models
{
/// <summary>
/// 身份验证信息 模拟JWT的payload
/// </summary>
public class AuthInfo
{
/// <summary>
/// name
/// </summary>
public string Name { get; set; }
/// <summary>
/// Email
/// </summary>
public string Email { get; set; }
/// <summary>
/// role
/// </summary>
public List<string> Roles { get; set; }
/// <summary>
/// is admin
/// </summary>
public bool IsAdmin { get; set; }
/// <summary>
/// expiry date
/// </summary>
public DateTime? ExpiryDateTime { get; set; }
}
}
BondAttr.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace THC.Models
{
public class BondAttr
{
public string Cusip { get; set; }
public string Desc { get; set; }
public double Cpn { get; set; }
public string TrancheType { get; set; }
public string CpnType { get; set; }
public double Formula { get; set; }
public double WAM { get; set; }
public double Age { get; set; }
public double OFSize { get; set; }
public double CFSize { get; set; }
public double Price { get; set; }
public double WAL { get; set; }
public double Yield { get; set; }
public double Duration { get; set; }
}
}
LoginRequest.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace THC.Models
{
/// <summary>
/// 登录用户信息
/// </summary>
public class LoginRequest
{
/// <summary>
/// user
/// </summary>
public string UserName { get; set; }
/// <summary>
/// ps
/// </summary>
public string Password { get; set; }
/// <summary>
/// email
/// </summary>
public string UserEmail { get; set; }
}
}
TokenInfo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace THC.Models
{
/// <summary>
/// 生成的口令信息
/// </summary>
public class TokenInfo
{
/// <summary>
/// 是否成功
/// </summary>
public bool Success { get; set; }
/// <summary>
/// 令牌
/// </summary>
public string Token { get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string Message { get; set; }
}
}
Web.Config
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
https://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.7.2" />
<httpRuntime targetFramework="4.7.2" />
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" />
</namespaces>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<!--<remove name="OPTIONSVerbHandler" />-->
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headres" value="*"/>
<add name="Access-Control-Allow-Methods" value="*"/>
</customHeaders>
</httpProtocol>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\"Web\" /optionInfer+" />
</compilers>
</system.codedom>
</configuration>
至此T1和T2也完成了,所以的代码都可以通过,我们通过IIS Express部署两个api,然后用PostMain是测试单点登录和JWT验证
先在THC中登录。获取Token
然后在THC下面请求数据,如果直接请求,会提示没有验证
所以我添加了auth验证,然后把上面获得的Token赋给value,这样就能获取数据了,这说明JWT加密和解密在同域下可以用的
然后我们MBSSource发送请求https://localhost:44367/api/bonds/BidBond,想不通过验证直接获取数据,提醒一下,我们的目的不就是在T1(THC)上登录,可以访问数据,然后再T2(MBSSource)上,我们发现T1已经登录过了,就不需要再登录了,实现单点登录的方便性,所以我们在T2上不请求登录,直接发送数据请求,结果。。。,
直接请求肯定不行,需要把T1登录获取的Token当作T2数据请求Header传递给T2的API,结果便成功的获取了从T2返回的数据
至此所有工作都结束了,希望对大家有帮助,上面的是全部代码,有需要整个工程包的,可以私信我,谢谢