开发了一个公司内部系统,使用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. 记一次在Grafana中使用Worldmap Panel的经历

    背景 因与工作相关,以下内容皆做了脱敏处理 主要的需求是要根据地理位置查看可视化的数据. 安装及创建 安装命令来源于官网 grafana-cli plugins install grafana-wor ...

  2. CSS 的层叠上下文是什么

    层叠上下文是 HTML 中的一个三维的概念,每个层叠上下文中都有一套元素的层叠排列顺序.页面根元素天生具有层叠上下文,所以整个页面处于一个“层叠结界”中. 层叠上下文的创建: 页面根元素:html z ...

  3. VulnHub::DC-1

    实验环境 一共有五个flag,有多种方法去提权,我们最终目标是去拿到/root的flag.总的来说,难度不高,适合新人练手 渗透过程 0x01 信息搜集 由于不知道靶机IP地址,进行D段扫描,获得靶机 ...

  4. C#-性能-二维数组和数组的数组的性能比较

    两者是3:2的消耗比例 const int NUM = 10000; int[,] vec = new int[NUM, NUM]; Stopwatch sw = Stopwatch.StartNew ...

  5. 原来不只是fastjson,这个你每天都在用的类库也被爆过反序列化漏洞!

    GitHub 15.8k Star 的Java工程师成神之路,不来了解一下吗! GitHub 15.8k Star 的Java工程师成神之路,真的不来了解一下吗! GitHub 15.8k Star ...

  6. OSCP Learning Notes - Scanning(1)

    TCP vs UDP TCP: Connection-oriented Suited for applications that require high reliablity[HTTP, FTP,T ...

  7. split().reverse().join()代码解析

    split() 方法用于把一个字符串分割成字符串数组. reverse() 方法用于颠倒数组中元素的顺序. join() 方法用于把数组中的所有元素放入一个字符串.

  8. 技术干货:Jenkins集成GitLab

    Jenkins免密拉取GitLab项目 1.在Jenkins上为GitLab创建一个专有的拉取代码的账号 Jenkins需要构建哪些项目就在GitLab给予账号相应权限 我这里已经创建过Jenkins ...

  9. Python 脚本语言

    python 脚本语言(python的命名起源于一个脚本screenplay,每次运行都会使对话框逐字重复.由著名的“龟叔”Guido van Rossum在1989年圣诞节期间编写.) Python ...

  10. vue中使用触摸事件,上滑,下滑,等

    第一步,下载一个包 npm install kim-vue-touch -s 在当前项目中下载包 第二部 import vueTouch from 'kim-vue-touch' Vue.use(vu ...