asp.net core MVC之实现基于token的认证

asp.net core mvc之实现基于token的认证

安装nuget包

项目中添加包:dotnet add package microsoft.aspnetcore.authentication.jwtbearer

添加认证配置

startup类中添加如下配置:

public void configureservices(iservicecollection services)
{
  ...
  services.addauthentication(defaultscheme: jwtbearerdefaults.authenticationscheme);
}

public void configure(iapplicationbuilder app, iwebhostenvironment env)
{
  ...
  app.useauthentication();
  app.useauthorization();
  app.useendpoints(endpoints =>
  {
      endpoints.mapcontrollers();
  }); 
}

addauthentication方法会向依赖注入容器添加认证服务和它所使用的其他服务,其参数defaultscheme用于指定当未指定具体的认证方案时将会使用的默认方案,上例为bearer认证。

addauthentication方法的另一重载能够使用authenticationoptions类为认证过程中的每一个动作指明所使用的认证方案,如defaultauthenticatescheme、
defaultchallengescheme、
defaultsigninscheme、
defaultsignoutscheme、
defaultforbidscheme。
如果没有为这些属性设置认证方案,则将使用defaultscheme属性所指定的值。

当添加jwtbearer认证方式时,jwtbeareroptions对象能够配置该认证的选项,它的tokenvalidationparameters属性用于指定验证token时的规则:

var tokensection = configuration.getsection("security:token");
services.addauthentication(options => {
  options.defaultauthenticatescheme = jwtbearerdefaults.authenticationscheme;
  options.defaultchallengescheme = jwtbearerdefaults.authenticationscheme;
}).addjwtbearer(options => {
  options.tokenvalidationparameters = new tokenvalidationparameters{
      validateaudience = true,
      validatelifetime = true,
      validateissuer = true,
      validateissuersigningkey = true,
      validissuer = tokensection["issuer"],
      validaudience = tokensection["audience"],
      issuersigningkey = new symmetricsecuritykey(
          encoding.utf8.getbytes(tokensection["key"])
      ),
      clockskew = timespan.zero
  };
});

tokenvalidationparameters类作为token验证参数类,它包含了一些属性,这些属性如validateaudience、validateissuer、validatelifetime和validateissuersigningkey,它们都是布尔类型,用于指明是否验证相应的项;而validissuer和validaudience属性则用于指明合法的签发者(issuer)与接受方(audience)。在上例中,它们的值都从配置文件中获取;issuersigningkey属性的值用于指定进行签名验证的安全密钥,它的值为symmetricsecuritykey对象,即对称加密密钥;clockskew属性的值表示验证时间的时间偏移值。

上述代码会从配置文件中读取关于token的信息,因此还需在appsettings.json中添加如下内容。

"security": {
"token": {
  "issuer": "demo_issuer",
  "audience": "demo_audience",
  "key": "<your_secret_key>"
}
}

为controller添加认证

接下来,为了使用asp.net core的认证功能来保护资源,应为controller或action添加[authorize]特性,该特性能够实现在访问相应的controller或action时,要求请求方提供指定的认证方式,它位于microsoft.aspnetcore.authorization命名空间中。需要为authorcontroller和bookcontroller添加该特性。

[authorize]
public class authorcontroller : controllerbase
{
}
[authorize(authenticationschemes = jwtbearerdefaults.authenticationscheme)]
public class bookcontroller : controllerbase
{
}

如果使用了多个认证方式,则可以使用[authorize]特性的authenticationschemes属性指明当前controller或action要使用哪一种认证方式(如上例中的bookcontroller);如果不设置,则会使用所添加认证时设置的默认方案;如果没有设置默认方案,则会出现invalidoperationexception异常,并提示未指定默认方案;此外,如果为authenticationschemes属性指定了不存在的方案名称,也会出现invalidoperationexception异常。

此时再访问book和author资源,会出现401 unauthorized异常:

如果要允许某个action可以被匿名访问,可以在action方法上添加属性标记 [allowanonymous]:

[allowanonymous]
public async task<actionresult<ienumerable<authordto>>> getauthorsasync([fromquery] authorresourceparameters parameters)

添加认证信息生成接口

jwtbearer中间件提供了对jwt的验证功能,然而并未提供生成token的功能。要生成token,可以使用jwtsecuritytokenhandler类,它位于system.identitymodel.tokens.jwt命名空间,它不仅能够生成jwt,由于它实现了isecuritytokenvalidator接口,因此对jwt的验证也是由它完成的。接下来,我们将创建一个controller,它将会根据用户的认证信息生成jwt,并返回给客户端。

在controllers文件夹中创建一个controller,名为authenticatecontroller,内容如下:

using system;
using system.collections.generic;
using system.identitymodel.tokens.jwt;
using system.security.claims;
using system.text;
using microsoft.aspnetcore.mvc;
using microsoft.extensions.configuration;
using microsoft.identitymodel.tokens;

namespace library.api.controllers
{
  [apicontroller, route("api/auth")]
  public class authenticatecontroller : controllerbase
  {
      public iconfiguration configuration { get; }
      public authenticatecontroller(iconfiguration configuration)
      {
          configuration = configuration;
      }

      [httppost("token", name = nameof(generatetoken))]
      public iactionresult generatetoken(string username, string password)
      {
          if (username != "demouser" || password != "demopassword")
          {
              return unauthorized();
          }

          var claims = new list<claim>{
              new claim(jwtregisteredclaimnames.sub, username)
          };

          var tokenconfigsection = configuration.getsection("security:token");
          var key = new symmetricsecuritykey(
              encoding.utf8.getbytes(tokenconfigsection["key"])
          );
          var signcredential = new signingcredentials(key, securityalgorithms.hmacsha256);
          var jwttoken = new jwtsecuritytoken(
              issuer: tokenconfigsection["issuer"],
              audience: tokenconfigsection["audience"],
              claims: claims,
              expires: datetime.now.addminutes(3),
              signingcredentials: signcredential
          );

          return ok(new {
              token = new jwtsecuritytokenhandler().writetoken(jwttoken),
              expiration = timezoneinfo.converttimefromutc(jwttoken.validto, timezoneinfo.local)
          });
      }
  }
}

在authenticatecontroller中的generatetoken方法中,通过创建jwtsecuritytoken对象,并使用jwtsecuritytokenhandler对象的writetoken方法最终得到生成的jwt。当创建jwtsecuritytoken对象时,我们可以指定issuer、audience以及当前用户的claim信息,此外,还可以指定该token的有效时间。这里需要注意,由于jwt不支持销毁以及撤回功能,因此在设置它的有效时间时,应设置一个较短的时间(如上例中的3分钟),这样可以有效避免token在意外被窃取后所带来的风险。

现在就可以请求认证接口获取 token:

这时重新请求资源接口,在请求头中添加authorization项,值为bearer ,就可以得到结果了:

这次示例中,使用了固定的用户名和密码,实际情况中,用户名和密码通常是存在数据库中的,可以使用asp.net core identity来实现这一功能。

关于asp.net core mvc之实现基于token的认证的文章就介绍至此,更多相关asp.net core token的认证内容请搜索硕编程以前的文章,希望大家多多支持硕编程

下一节:如何在 .net 中使用 flurl 高效处理http请求

asp.net编程技术

相关文章