6月15日,在端午节前的最后一个工作日,想起有段日子没有写过文章了,倒有些荒疏了。今借夏日蒸蒸之气,偷得浮生半日悠闲。闲话就说到这里吧,提前祝大家端午愉快(屈原听了该不高兴了:))!
.NetCore自发布以来,颇受关注,现在.Net Core2.0已经正式发布,边迫不及待的将.Net跨平台移植的工作进行到底。想来,也费不了多少事儿。我经常和同事们说,要敢于尝试新鲜事物,不阴损守旧,方能使自己不断进步,站在队伍的前列。下面就关于Asp.Net Core在Web 及API项目上身份认证的问题做下简单的阐述。

一、Asp.Net Core Web项目的登录认证

在MVC Web项目中,做用户登录授权,是必不可少的工作,不知道大家平时是怎么做的,我想,大多朋友还是使用微软提供的一套认证机制,可以省去很多功夫。从WebForm时代的Form身份认证,无非是通过客户端Cookie中存储认证票据,在请求受保护的资源时,通过Cookie中携带的身份票据,再有Asp.net的认证模块,完整对请求者的身份认证。这一过程,是很清晰简单的了。在MVC中,大多是通过中间件(MiddleWare)来完整认证授权过程。在ASP.NETMVC中,我们了解到基于声明的授权认证(Claim),这种认证方式,好处在于,我们想在用户授权时,存储多个属性信息,只需要添加多个声明即可,我们在微软的认证中间件中,看到的都是定义好的常量,当然,我们可以定义自己的ClaimTypes。然我们看看微软在.NetCore中定义的一些声明吧:

 //
// Summary:
// http://schemas.xmlsoap.org/ws/2009/09/identity/claims/actor.
public const string Actor = "http://schemas.xmlsoap.org/ws/2009/09/identity/claims/actor";
//
// Summary:
// The URI for a claim that specifies the postal code of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/postalcode.
public const string PostalCode = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/postalcode";
//
// Summary:
// The URI for a claim that specifies the primary group SID of an entity, http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid.
public const string PrimaryGroupSid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid";
//
// Summary:
// The URI for a claim that specifies the primary SID of an entity, http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid.
public const string PrimarySid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid";
//
// Summary:
// The URI for a claim that specifies the role of an entity, http://schemas.microsoft.com/ws/2008/06/identity/claims/role.
public const string Role = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
//
// Summary:
// The URI for a claim that specifies an RSA key, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/rsa.
public const string Rsa = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/rsa";
//
// Summary:
// The URI for a claim that specifies a serial number, http://schemas.microsoft.com/ws/2008/06/identity/claims/serialnumber.
public const string SerialNumber = "http://schemas.microsoft.com/ws/2008/06/identity/claims/serialnumber";
//
// Summary:
// The URI for a claim that specifies a security identifier (SID), http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sid.
public const string Sid = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sid";
//
// Summary:
// The URI for a claim that specifies a service principal name (SPN) claim, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/spn.
public const string Spn = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/spn";
//
// Summary:
// The URI for a claim that specifies the state or province in which an entity resides,
// http://schemas.xmlsoap.org/ws/2005/05/identity/claims/stateorprovince.
public const string StateOrProvince = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/stateorprovince";
//
// Summary:
// The URI for a claim that specifies the street address of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/streetaddress.
public const string StreetAddress = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/streetaddress";
//
// Summary:
// The URI for a claim that specifies the surname of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname.
public const string Surname = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname";
//
// Summary:
// The URI for a claim that identifies the system entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/system.
public const string System = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/system";
//
// Summary:
// The URI for a claim that specifies a thumbprint, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/thumbprint.
// A thumbprint is a globally unique SHA-1 hash of an X.509 certificate.
public const string Thumbprint = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/thumbprint";
//
// Summary:
// The URI for a claim that specifies a user principal name (UPN), http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn.
public const string Upn = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn";
//
// Summary:
// The URI for a claim that specifies a URI, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/uri.
public const string Uri = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/uri";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata.
public const string UserData = "http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/version.
public const string Version = "http://schemas.microsoft.com/ws/2008/06/identity/claims/version";
//
// Summary:
// The URI for a claim that specifies the webpage of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/webpage.
public const string Webpage = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/webpage";
//
// Summary:
// The URI for a claim that specifies the Windows domain account name of an entity,
// http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname.
public const string WindowsAccountName = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdeviceclaim.
public const string WindowsDeviceClaim = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdeviceclaim";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdevicegroup.
public const string WindowsDeviceGroup = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdevicegroup";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsfqbnversion.
public const string WindowsFqbnVersion = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsfqbnversion";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/windowssubauthority.
public const string WindowsSubAuthority = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowssubauthority";
//
// Summary:
// The URI for a claim that specifies the alternative phone number of an entity,
// http://schemas.xmlsoap.org/ws/2005/05/identity/claims/otherphone.
public const string OtherPhone = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/otherphone";
//
// Summary:
// The URI for a claim that specifies the name of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier.
public const string NameIdentifier = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier";
//
// Summary:
// The URI for a claim that specifies the name of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name.
public const string Name = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name";
//
// Summary:
// The URI for a claim that specifies the mobile phone number of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone.
public const string MobilePhone = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone";
//
// Summary:
// The URI for a claim that specifies the anonymous user; http://schemas.xmlsoap.org/ws/2005/05/identity/claims/anonymous.
public const string Anonymous = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/anonymous";
//
// Summary:
// The URI for a claim that specifies details about whether an identity is authenticated,
// http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authenticated.
public const string Authentication = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authentication";
//
// Summary:
// The URI for a claim that specifies the instant at which an entity was authenticated;
// http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant.
public const string AuthenticationInstant = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant";
//
// Summary:
// The URI for a claim that specifies the method with which an entity was authenticated;
// http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod.
public const string AuthenticationMethod = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod";
//
// Summary:
// The URI for a claim that specifies an authorization decision on an entity; http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authorizationdecision.
public const string AuthorizationDecision = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authorizationdecision";
//
// Summary:
// The URI for a claim that specifies the cookie path; http://schemas.microsoft.com/ws/2008/06/identity/claims/cookiepath.
public const string CookiePath = "http://schemas.microsoft.com/ws/2008/06/identity/claims/cookiepath";
//
// Summary:
// The URI for a claim that specifies the country/region in which an entity resides,
// http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country.
public const string Country = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country";
//
// Summary:
// The URI for a claim that specifies the date of birth of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth.
public const string DateOfBirth = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth";
//
// Summary:
// The URI for a claim that specifies the deny-only primary group SID on an entity;
// http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid.
// A deny-only SID denies the specified entity to a securable object.
public const string DenyOnlyPrimaryGroupSid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid";
//
// Summary:
// The URI for a claim that specifies the deny-only primary SID on an entity; http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid.
// A deny-only SID denies the specified entity to a securable object.
public const string DenyOnlyPrimarySid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid";
//
// Summary:
// The URI for a claim that specifies a deny-only security identifier (SID) for
// an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid.
// A deny-only SID denies the specified entity to a securable object.
public const string DenyOnlySid = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsuserclaim.
public const string WindowsUserClaim = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsuserclaim";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlywindowsdevicegroup.
public const string DenyOnlyWindowsDeviceGroup = "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlywindowsdevicegroup";
//
// Summary:
// http://schemas.microsoft.com/ws/2008/06/identity/claims/dsa.
public const string Dsa = "http://schemas.microsoft.com/ws/2008/06/identity/claims/dsa";
//
// Summary:
// The URI for a claim that specifies the email address of an entity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/email.
public const string Email = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";

    那么我们在Asp.Net Core项目中的认证,也是比较简单的。也是通过HttpContext的扩展方法SignInAsync,来传入声明的身份信息。要使用的微软的认证组件,我们在.Net Core Web项目中,做如下改动:

首先,在Start.cs类中,添加服务,具体代码如下:

         /// <summary>
///
/// </summary>
/// <param name="services"></param>
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o =>
{
o.Cookie.Name = "_AdminTicketCookie";
o.LoginPath = new PathString("/Account/Login");
o.LogoutPath = new PathString("/Account/Login");
o.AccessDeniedPath = new PathString("/Error/Forbidden");
});
services.AddTransient<TiKu.Application.Interfaces.IAdminService, TiKu.Application.AdminService>();
services.AddMvc();
}

    其次,添加认证中间件

        /// <summary>
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
/// </summary>
/// <param name="app"></param>
/// <param name="env"></param>
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{ if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseAuthentication();//添加认证中间件
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
}); }

  最后,在用户登录的地方,登录成功后,调用HttpContext的SignIn方法,将授权信息写入Cookie,示例代码如下:

        /// <summary>
/// <![CDATA[登陆]]>
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(Models.LoginViewModel model)
{
try
{
//模型验证通过后
if (ModelState.IsValid)
{
model.password = TiKu.Common.Security.MD5.Md5(model.password);//MD5加密
TiKu.Domain.Entity.tb_Admin admin = await _AdminService.CheckAccountAndPassword(account: model.account, password: model.password);
//验证用户名密码
if (admin != null)
{
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);//一定要声明AuthenticationScheme
identity.AddClaim(new Claim(ClaimTypes.Name, admin.Account));
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, admin.Id.ToString())); await HttpContext.SignInAsync(identity.AuthenticationType,
new ClaimsPrincipal(identity),
new AuthenticationProperties
{
IsPersistent = model.isPersistent,
RedirectUri = "/Home/Index",
ExpiresUtc = new System.DateTimeOffset(dateTime: DateTime.Now.AddHours(6)),
});
//更新登陆时间
await _AdminService.UpdateLastLoginTime(id: admin.Id);
}
else
{
await HttpContext.ChallengeAsync(CookieAuthenticationDefaults.AuthenticationScheme);
ModelState.AddModelError("", "用户名或密码错误!");
}
}
}
catch (Exception ex)
{
ModelState.AddModelError("", "用户名或密码错误!");
_Logger.Error("用户登录时发生错误!", ex);
}
return View(model);
}

  这样就完成了Asp.net core web项目的登录认证工作。

二、Asp.Net Core WebApi基于JWT的认证授权

      关于JWT的工作原理,大家可以自行了解(https://jwt.io/)。JWT实现了服务端无状态,在分布式服务,会话一致性,单点登录等方面,凸显优势,不占用服务端资源。使用JWT需要注意的是,令牌过期后刷新,以及更改密码后令牌未过期的处理问题。

这里,我以JWT作为.net core webapi项目的认证方式。

首先,我再Api项目中新建了一个名为OAuthController的控制器,定义一个Action名为Token的方法,用来让客户端获取令牌之用,具体代码如下:

        /// <summary>
/// <![CDATA[获取访问令牌]]>
/// </summary>
/// <param name="user"></param>
/// <param name="password"></param>
/// <returns></returns>
[HttpPost]
public async Task<TiKu.Domain.ValueObject.RestfulData<TiKu.Domain.ValueObject.AccessTokenObj>> Token(string user, string password)
{
var result = new TiKu.Domain.ValueObject.RestfulData<TiKu.Domain.ValueObject.AccessTokenObj>();
try
{
if (string.IsNullOrEmpty(user)) throw new ArgumentNullException("user", "用户名不能为空!");
if (string.IsNullOrEmpty(password)) throw new ArgumentNullException("password", "密码不能为空!"); //验证用户名和密码
var userInfo = await _UserService.CheckUserAndPassword(mobile: user, password: password);
var claims = new Claim[]
{
new Claim(ClaimTypes.Name,user),
new Claim(ClaimTypes.NameIdentifier,userInfo.Id.ToString()),
}; var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(Configuration["JwtSecurityKey"]));
var expires = DateTime.Now.AddDays(28);//
var token = new JwtSecurityToken(
issuer: Configuration["issuer"],
audience: Configuration["audience"],
claims: claims,
notBefore: DateTime.Now,
expires: expires,
signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)); //生成Token
string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);
result.code = 1;
result.data = new Domain.ValueObject.AccessTokenObj() { AccessToken = jwtToken, Expires = TiKu.Common.Utility.Util.ToUnixTime(expires) };
result.message = "授权成功!";
return result;
}
catch (Exception ex)
{
result.message = ex.Message;
result.code = 0;
logger.Error("获取访问令牌时发生错误!", ex);
return result;
}
}

  这里,我定义了一个统一返回数据格式的模型-RestfulData,其中有不返回数据data的RestfulData和带data数据的RestfulData<T>,以及返回集合类型的RestfulArray<T>,具体代码如下:

  /// <summary>
///
/// </summary>
public class RestfulData
{
/// <summary>
/// <![CDATA[错误码]]>
/// </summary>
public int code { get; set; } /// <summary>
///<![CDATA[消息]]>
/// </summary>
public string message { get; set; } /// <summary>
/// <![CDATA[相关的链接帮助地址]]>
/// </summary>
public string url { get; set; } } /// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
public class RestfulData<T> : RestfulData
{
/// <summary>
/// <![CDATA[数据]]>
/// </summary>
public virtual T data { get; set; }
} /// <summary>
/// <![CDATA[返回数组]]>
/// </summary>
/// <typeparam name="T"></typeparam>
public class RestfulArray<T> : ResultData<IEnumerable<T>>
{ }

  

配置JWT认证服务,在Start.cs启动类中,配置如下:

/// <summary>
///
/// </summary>
/// <param name="services"></param>
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfiguration>(Configuration);
services.AddMemoryCache();//添加基于内存的缓存支持
services.AddAutofac(); //配置授权
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "JwtBearer";
options.DefaultChallengeScheme = "JwtBearer"; }).AddJwtBearer("JwtBearer",
(jwtBearerOptions) =>
{
jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(Configuration["JwtSecurityKey"])),//秘钥
ValidateIssuer = true,
ValidIssuer = Configuration["issuer"],
ValidateAudience = true,
ValidAudience = Configuration["audience"],
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes(5)
};
}); services.AddMvc(); //IOC Autofac
var builder = new ContainerBuilder();
builder.Populate(services); //注册应用服务
var assemblyApplicationService = System.Reflection.Assembly.Load("TiKu.Application");
builder.RegisterAssemblyTypes(assemblyApplicationService).AsImplementedInterfaces(); var container = builder.Build();
Container = container; return new AutofacServiceProvider(container);
}

  上面使用了IOC容器Autofac。

其次,配置认证中间件:

        /// <summary>
///
/// </summary>
/// <param name="app"></param>
/// <param name="env"></param>
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();//配置授权
//处理异常
app.UseStatusCodePages(new StatusCodePagesOptions()
{
HandleAsync = (context) =>
{
if (context.HttpContext.Response.StatusCode == 401)
{
using (System.IO.StreamWriter sw = new System.IO.StreamWriter(context.HttpContext.Response.Body))
{
sw.Write(Newtonsoft.Json.JsonConvert.SerializeObject(new
{
status = 401,
message = "access denied!",
}));
}
}
return System.Threading.Tasks.Task.Delay(0);
}
});
app.UseMvc(routes =>
{
routes.MapRoute(name: "default", template: "api/{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(name: "mvc", template: "{controller=Home}/{action=Index}/{id?}");
});
}  

为了测试,我们给ValuesController控制器添加Authorize特性。

    /// <summary>
///
/// </summary>
[Authorize]
[Route("api/[controller]")]
public class ValuesController : Controller
{ // GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
} 

最后,让我们测试下API的授权,这里,我以Ajax模拟API的调用:

script type="text/javascript">
//获取令牌
$.post("/oauth/token", $.param({ user: "lichaoqiang", password: "fdsfds" })).done(function (data) { if (data.code === 1) {
localStorage.setItem("token", data.data.accessToken);
}
}); //设置HTTP头
$.ajaxSetup({
beforeSend: function (xhr) {
if (localStorage.getItem("token") !== null) {
xhr.setRequestHeader('Authorization', 'Bearer ' + localStorage.getItem("token"));
}
}
}); $.getJSON("/api/values", function (data) { console.log(data); });//获取受保护的资源
</script>

  看下效果,直接访问/api/values,会出现如下图:

当客户请求受保护的资源时,通过HTTP header携带上token。这里需要注意的是,请求头必须是Authorization,值是Bearer空格加上token。这样访问资源时,通过HTTP header携带令牌信息,服务端,通过认证中间件,完成授权认证过程。在上面的示例中,通过向全局Ajax注册事件,将token写入请求Header。、

至此,就完成了JWT认证授权的过程,.Net Core WebAPI配置起来也很简单。

关于ASP.Net Core Web及API身份认证的解决方案的更多相关文章

  1. ASP.NET Core系列:JWT身份认证

    1. JWT概述 JSON Web Token(JWT)是目前流行的跨域身份验证解决方案. JWT的官网地址:https://jwt.io JWT的实现方式是将用户信息存储在客户端,服务端不进行保存. ...

  2. ASP.NET CORE中使用Cookie身份认证

    大家在使用ASP.NET的时候一定都用过FormsAuthentication做登录用户的身份认证,FormsAuthentication的核心就是Cookie,ASP.NET会将用户名存储在Cook ...

  3. ASP.NET Core的无状态身份认证框架IdentityServer4

    Identity Server 4是IdentityServer的最新版本,它是流行的OpenID Connect和OAuth Framework for .NET,为ASP.NET Core和.NE ...

  4. ASP.NET Core编程实现基本身份认证

    概览 在HTTP中,基本认证(Basic access authentication,简称BA认证)是一种用来允许网页浏览器或其他客户端程序在请求资源时提供用户名和口令形式的身份凭证的一种登录验证方式 ...

  5. 理解ASP.NET Core - 基于Cookie的身份认证(Authentication)

    注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 概述 通常,身份认证(Authentication)和授权(Authorization)都会放 ...

  6. ASP.NET Core如何使用WSFederation身份认证集成ADFS

    如果要在ASP.NET Core项目中使用WSFederation身份认证,首先需要在项目中引入NuGet包: Microsoft.AspNetCore.Authentication.WsFedera ...

  7. 理解ASP.NET Core - 基于JwtBearer的身份认证(Authentication)

    注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 在开始之前,如果你还不了解基于Cookie的身份认证,那么建议你先阅读<基于Cookie ...

  8. ASP.NET Core 3.0 gRPC 身份认证和授权

    一.开头聊骚 本文算是对于 ASP.NET Core 3.0 gRPC 研究性学习的最后一篇了,以后在实际使用中,可能会发一些经验之文.本文主要讲 ASP.NET Core 本身的认证授权和gRPC接 ...

  9. 【译】使用Jwt身份认证保护 Asp.Net Core Web Api

    原文出自Rui Figueiredo的博客,原文链接<Secure a Web Api in ASP.NET Core> 摘要:这边文章阐述了如何使用 Json Web Token (Jw ...

随机推荐

  1. 数据库TCPIP协议开了,但还是远程连不上

    可能是因为开着防火墙 把防火墙关掉,或者参考下面的链接,在防火墙添加例外 https://zhidao.baidu.com/question/394026326542219285.html

  2. js的一些总结

    函数 函数是一等公民 函数可以有属性,并且能连接到它的构造方法 函数可以像一个变量一样存在内存中 函数可以当做参数传给其他函数 函数可以返回其他函数 加法操作表 Number + Number -&g ...

  3. 四 分析easyswoole源码(启动服务&Cache组件原理)

    前文提到的在系统设置Cache组件 Cache::getInstance()的时候,会去调用processManager去创建Cache的进程,然后以管道通信的方式进行设置缓存和获取缓存. Cache ...

  4. SPS Programming Abrites AVDI or GM MDI

    Just information for you to make a wise purchase of GM scan tools for SPS programming: (here, I focu ...

  5. activeMq-3 Spring整合activeMq

    与jdbcTemplate相似的是,Spring也提供了JmsTemplate 生产者使用JmsTemplate生产消息,消费者实现一个监听器用于获取消息 项目用maven构建,jdk1.8, 文末提 ...

  6. 201771010142 张燕《面向对象程序设计(java)》第一周学习总结

    201771010142 张燕<面向对象程序设计(java)>第一周学习总结 第一部分:课程准备部分 填写课程学习 平台注册账号, 平台名称 注册账号 博客园:www.cnblogs.co ...

  7. kbmmw中向服务器端传递对象的一种简单方式

    运行环境:delphi 10.2+kbmmw 5.6.20 在kbmmw 的老版本中,要向服务器传送一个本地的对象,一般都需要进行一些转换,例如通过序列化的方式. 在新版的kbmmw中这一切都变的很简 ...

  8. this guy gonna be a daddy

    时间真快,媳妇儿怀孕了两个月了. 2016年2月10日,在横峰血检后确定媳妇儿怀孕后,我心情激动得要飞起来一样,那时,我在心里告诉自己不是个孩子了,我自己即将成为孩子的父亲.当时只顾着自个儿激动,已经 ...

  9. 参考文献bib管理

    比如在IEEE模板中,在当前目录添加 bib 文件reference.bib 在 \end{document} 之前加入 \bibliographystyle{IEEEtran} \bibliogra ...

  10. Python数字与字符之间的转换

    Python数字与字符之间的转换 命令 意义 int(x [,base ]) 将x转换为一个整数 long(x [,base ]) 将x转换为一个长整数 float(x ) 将x转换到一个浮点数 co ...