开发了一个公司内部系统,使用asp.net core 3.1。在开发用户认证授权使用的是简单的cookie认证方式,然后开发好了要写几个接口给其它系统调用数据。并且只是几个简单的接口不准备再重新部署一个站点,所以就直接在MVC的项目里面加了一个API区域用来写接口。这时候因为是接口所以就不能用cookie方式进行认证,得加一个jwt认证,采用多种身份验证方案来进行认证授权。

认证授权

身份验证是确定用户身份的过程。 授权是确定用户是否有权访问资源的过程。 在 ASP.NET Core 中,身份验证由 IAuthenticationService 负责,而它供身份验证中间件使用。 身份验证服务会使用已注册的身份验证处理程序来完成与身份验证相关的操作。

认证-->授权

关于认证授权我们要区分认证和授权是两个概念,具体可查看MSDN官方文档也可以搜索其它文章看看,讲的很多。其中包括OAuth 2.0 以及jwt的相关知识都有很多资料并且讲解的很好。

身份认证

身份验证方案由 Startup.ConfigureServices 中的注册身份验证服务指定:

方式是在调用 services.AddAuthentication 后调用方案特定的扩展方法(例如 AddJwtBearer 或 AddCookie)。 这些扩展方法使用 AuthenticationBuilder.AddScheme 向适当的设置注册方案。

  • 添加cookie JwtBearer验证方案
public void ConfigureServices(IServiceCollection services)
{
services.AddSession();
services.AddMvc(o =>
{
o.Filters.Add(typeof(MyExceptionFilterAttribute));// 全局异常Filter
}).AddRazorRuntimeCompilation();
//添加身份认证方案
var jwtConfig= Configuration.GetSection("Jwt").Get<JwtConfig>();
services.AddAuthentication
(authoption =>{
//指定默认选项
authoption.DefaultChallengeScheme= CookieAuthenticationDefaults.AuthenticationScheme;
authoption.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
authoption.DefaultSignOutScheme = CookieAuthenticationDefaults.AuthenticationScheme;
authoption.DefaultSignInScheme= CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, option =>
{
option.Cookie.Name = "adCookie";//设置存储用户登录信息(用户Token信息)的Cookie名称
option.Cookie.HttpOnly = true;//设置存储用户登录信息(用户Token信息)的Cookie,无法通过客户端浏览器脚本(如JavaScript等)访问到
option.ExpireTimeSpan = TimeSpan.FromDays(3);// 过期时间
option.SlidingExpiration = true;// 是否在过期时间过半的时候,自动延期
option.LoginPath = "/Account/Login";
option.LogoutPath = "/Account/LoginOut";
})
.AddJwtBearer(option =>
{
option.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = jwtConfig.Issuer,
ValidAudience = jwtConfig.Audience,
ValidateIssuer = true,
ValidateLifetime = jwtConfig.ValidateLifetime,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.SigningKey)),
//缓冲过期时间,总的有效时间等于这个时间加上jwt的过期时间
ClockSkew = TimeSpan.FromSeconds(0)
};
});
}
  • JwtBearer认证的配置参数类JwtConfig
public class JwtConfig
{
/// <summary>
/// 谁颁发的
/// </summary>
public string Issuer { get; set; } /// <summary>
/// 颁发给谁
/// </summary>
public string Audience { get; set; } /// <summary>
/// 令牌密码
/// a secret that needs to be at least 16 characters long
/// </summary>
public string SigningKey { get; set; } /// <summary>
/// 过期时间(分钟)
/// </summary>
public int Expires { get; set; } /// <summary>
/// 是否校验过期时间
/// </summary>
public bool ValidateLifetime { get; set; }
}
  • appsettings.json 配置参数
  "Jwt": {
"Issuer": "issuer",
"Audience": "audience",
"SigningKey": "c0d32c63-z43d-4917-bbc2-5e726d087452",
//过期时间(分钟)
"Expires": 10080,
//是否验证过期时间
"ValidateLifetime": true
}
  • 添加身份验证中间件

通过在应用的 IApplicationBuilder 上调用 UseAuthentication 扩展方法,在 Startup.Configure 中添加身份验证中间件。 如果调用 UseAuthentication,会注册使用之前注册的身份验证方案的中间节。 请在依赖于要进行身份验证的用户的所有中间件之前调用 UseAuthentication。 如果使用终结点路由,则必须按以下顺序调用 UseAuthentication:

● 在 UseRouting之后调用,以便路由信息可用于身份验证决策。

● 在 UseEndpoints 之前调用,以便用户在经过身份验证后才能访问终结点。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseSession();
app.UseRouting(); //开启认证中间件
app.UseAuthentication();
//开启授权中间件
app.UseAuthorization(); app.UseEndpoints(endpoints =>
{ endpoints.MapControllerRoute(
name: "areas",
pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"); endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
  • cookie认证
[HttpPost]
public async Task<NewtonsoftJsonResult> LoginIn(string userName, string userPassword, string code)
{
AjaxResult objAjaxResult = new AjaxResult();
var user = _userBll.GetUser(userName, userPassword);
if (user == null)
{
objAjaxResult.Result = DoResult.NoAuthorization;
objAjaxResult.PromptMsg = "用户名或密码错误";
}
else
{
var claims = new List<Claim>
{
new Claim("userName", userName),
new Claim("userID",user.Id.ToString()),
};
await HttpContext.SignInAsync(new ClaimsPrincipal(new ClaimsIdentity(claims,CookieAuthenticationDefaults.AuthenticationScheme)));
objAjaxResult.Result = DoResult.Success;
objAjaxResult.PromptMsg = "登录成功";
}
return new NewtonsoftJsonResult(objAjaxResult);
}
  • jwt认证
[HttpPost]
public NewtonsoftJsonResult Token([FromBody] UserInfo model)
{
AjaxResult objAjaxResult = new AjaxResult();
var user = _userBll.GetUser(model.UserName, model.Password);
if (user == null)
{
objAjaxResult.Result = DoResult.NoAuthorization;
objAjaxResult.PromptMsg = "用户名或密码错误";
}
else
{
//jwtTokenOptions 是通过配置获取上面配置的参数信息
var jwtTokenOptions = BaseConfigModel.jwtConfig;
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtTokenOptions.SigningKey));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
//身份
var claims = new List<Claim>
{
new Claim("userID",user.Id.ToString()),
new Claim("userName",user.UserName),
};
//令牌
var expires = DateTime.Now.AddMinutes(jwtTokenOptions.Expires);
var token = new JwtSecurityToken(
issuer: jwtTokenOptions.Issuer,
audience: jwtTokenOptions.Audience,
claims: claims,
notBefore: DateTime.Now,
expires: expires,
signingCredentials: credentials
);
string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);
objAjaxResult.Result = DoResult.Success;
objAjaxResult.RetValue = new
{
token = jwtToken
};
objAjaxResult.PromptMsg = "登录成功";
}
return new NewtonsoftJsonResult(objAjaxResult);
}

授权

在授权时,应用指示要使用的处理程序。 选择应用程序将通过以逗号分隔的身份验证方案列表传递到来授权的处理程序 [Authorize] 。 [Authorize]属性指定要使用的身份验证方案或方案,不管是否配置了默认。

  • 默认授权

    因为上面认证配置中我们使用cookie作为默认配置,所以前端对应的controller就不用指定验证方案,直接打上[Authorize]即可。

  • 选择授权

    对于API接口我们使用Jwt授权,在Controller上打上指定方案。
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

总结

关于多种方案混合验证授权的流程:

1、配置认证方案(相关的配置参数可采用配置文件形式)。

2、添加授权验证中间件。

3、提供认证接口。

4、配置需要授权的接口授权方案。

asp.net core 3.1多种身份验证方案,cookie和jwt混合认证授权的更多相关文章

  1. 坎坷路:ASP.NET Core 1.0 Identity 身份验证(中集)

    上一篇:<坎坷路:ASP.NET 5 Identity 身份验证(上集)> ASP.NET Core 1.0 什么鬼?它是 ASP.NET vNext,也是 ASP.NET 5,以后也可能 ...

  2. ASP.NET Core 项目简单实现身份验证及鉴权

    ASP.NET Core 身份验证及鉴权 目录 项目准备 身份验证 定义基本类型和接口 编写验证处理器 实现用户身份验证 权限鉴定 思路 编写过滤器类及相关接口 实现属性注入 实现用户权限鉴定 测试 ...

  3. 实践剖析.NET Core如何支持Cookie和JWT混合认证、授权

    前言 为防止JWT Token被窃取,我们将Token置于Cookie中,但若与第三方对接,调用我方接口进行认证.授权此时仍需将Token置于请求头,通过实践并联系理论,我们继续开始整活!首先我们实现 ...

  4. ASP.NET Core WebApi中使用FluentValidation验证数据模型

    原文链接:Common features in ASP.NET Core 2.1 WebApi: Validation 作者:Anthony Giretti 译者:Lamond Lu 介绍 验证用户输 ...

  5. 关于ASP.Net Core Web及API身份认证的解决方案

    6月15日,在端午节前的最后一个工作日,想起有段日子没有写过文章了,倒有些荒疏了.今借夏日蒸蒸之气,偷得浮生半日悠闲.闲话就说到这里吧,提前祝大家端午愉快(屈原听了该不高兴了:))!.NetCore自 ...

  6. HTTP 请求未经客户端身份验证方案“Anonymous”授权。从服务器收到的身份验证标头为“Negotiate,NTLM”

    转自:http://www.cnblogs.com/geqinggao/p/3270499.html 近来项目需要Web Service验证授权,一般有两种解决方案: 1.通过通过SOAP Heade ...

  7. 发布Restful服务时出现IIS 指定了身份验证方案错误时的解决方案(IIS specified authentication schemes)

    发布RESTful服务,当访问.svc文件时出现如下错误时: IIS 指定了身份验证方案“IntegratedWindowsAuthentication, Anonymous”,但绑定仅支持一种身份验 ...

  8. HTTP 请求未经客户端身份验证方案“Anonymous”授权。

    今天调取WebService的时候报: HTTP 请求未经客户端身份验证方案“Anonymous”授权. 解决办法: 配置文件里改: <basicHttpBinding> <bind ...

  9. 定制Asp.NET 5 MVC内建身份验证机制 - 基于自建SQL Server用户/角色数据表的表单身份验证

    背景 在需要进行表单认证的Asp.NET 5 MVC项目被创建后,往往需要根据项目的实际需求做一系列的工作对MVC 5内建的身份验证机制(Asp.NET Identity)进行扩展和定制: Asp.N ...

随机推荐

  1. EOS基础全家桶(十五)智能合约进阶2

    简介 今天我们继续补充智能合约的进阶使用技巧,这次的主题是交易,合约内我们除了可以发起内联action的调用,很多使用还需要直接调用其他的合约action或者以交易的形式调用自身的action. 发起 ...

  2. 【DevCloud · 敏捷智库】两种你必须了解的常见敏捷估算方法

    背景 在某开发团队辅导的回顾会议上,团队成员对于优化估计具体方法上达成了一致意见.询问是否有什么具体的估计方法来做估算. 问题分析 回顾意见上大家对本次Sprint的效果做回顾,其中80%的成员对于本 ...

  3. selenium 下拉到页面最底端

    selenium操控浏览器下拉到页面最底端: https://www.cnblogs.com/TTyb/p/7662430.html #!/usr/bin/env python # -*- codin ...

  4. 数据可视化之分析篇(七)Power BI数据分析应用:水平分析法

    https://zhuanlan.zhihu.com/p/103264851 首先,以财务报表分析为例,介绍通用的分析方法论,整体架构如下图所示: (点击查看大图) 接下来我会围绕这五种不同的方法论, ...

  5. Python面试【315+道题】

    第一部分 Python基础篇(80题) 为什么学习Python? 通过什么途径学习的Python? Python和Java.PHP.C.C#.C++等其他语言的对比? 简述解释型和编译型编程语言? P ...

  6. unity-编辑器快捷按键

    效果图 代码 [MenuItem("Custom/Run _F1")] static void PlayToggle() { EditorApplication.isPlaying ...

  7. bzoj2697特技飞行*

    bzoj2697特技飞行 题意: N个单位时间,每个单位时间可以进行一项特技动作,可选的动作有K种,每种动作有一个刺激程度Ci.每次动作的价值为(距上次该动作的时间)*Ci,若为第一次进行该动作,价值 ...

  8. Apache Avro & Avro Schema简介

    为什么需要schema registry? 首先我们知道: Kafka将字节作为输入并发布 没有数据验证 但是: 如果Producer发送了bad data怎么办? 如果字段被重命名怎么办? 如果数据 ...

  9. .NET Core微服务开发服务间调用篇-GRPC

    在单体应用中,相互调用都是在一个进程内部调用,也就是说调用发生在本机内部,因此也被叫做本地方法调用:在微服务中,服务之间调用就变得比较复杂,需要跨网络调用,他们之间的调用相对于与本地方法调用,可称为远 ...

  10. Python Ethical Hacking - MODIFYING DATA IN HTTP LAYER(1)

    MODIFYING DATA IN HTTP LAYER Edit requests/responses. Replace download requests. Inject code(html/Ja ...