欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

我的第一个netcore2.2 api项目搭建(三)

程序员文章站 2022-06-05 20:59:03
上一章快速陈述了自定义验证功能添加的过程,我的第一个netcore2.2 api项目搭建(三) 但是并没有真正的去实现,这一章将要实现验证功能的添加。 这一章实现目标三:jwt认证授权添加 在netcore2.2中,只要添加很简单的配置就能添加jwt功能了。至于jwt本身是啥大家自行去了解,这里不做 ......

上一章快速陈述了自定义验证功能添加的过程,我的第一个netcore2.2 api项目搭建(三)

但是并没有真正的去实现,这一章将要实现验证功能的添加。

这一章实现目标三:jwt认证授权添加

在netcore2.2中,只要添加很简单的配置就能添加jwt功能了。至于jwt本身是啥大家自行去了解,这里不做多说了。。

1.1添加jwthelper类

public class jwthelper
    {
        public const string audience = "jh.opemr.api";
        public const string issuer = "all";
        public const string signingkey = "my first security key";

        public static string createjwttoken(string uid, string uname, string sub)
        {
            var datetime = datetime.utcnow;
            var key = new symmetricsecuritykey(encoding.utf8.getbytes(signingkey));

            var tokenhandler = new jwtsecuritytokenhandler();
            var tokendescriptor = new securitytokendescriptor
            {
                subject = new claimsidentity(new claim[]
               {
                    new claim(jwtclaimtypes.audience,audience),
                    new claim(jwtclaimtypes.issuer,issuer),
                    new claim(jwtclaimtypes.id, uid),
                    new claim(jwtclaimtypes.name, uname),
                    new claim("role", sub)//高亮,很重要
               }),
                expires = datetime.addhours(0.5),
                signingcredentials = new signingcredentials(key, securityalgorithms.hmacsha256signature)
            };
            var token = tokenhandler.createtoken(tokendescriptor);
            var tokenstring = tokenhandler.writetoken(token);
            return tokenstring;
        }
    }

这个类就一个方法,提供生成加密的jwt串

1.2在startup做配置:

//注册默认认证方式,这里使用jwt方式
            services.addauthentication(x =>
            {
                x.defaultauthenticatescheme = jwtbearerdefaults.authenticationscheme;
                x.defaultchallengescheme = jwtbearerdefaults.authenticationscheme;
            }).addjwtbearer(o =>
               {
                   o.tokenvalidationparameters = new tokenvalidationparameters
                   {
                       roleclaimtype = jwtclaimtypes.role,//这个很重要

                       validissuer = jwthelper.issuer,
                       validaudience = jwthelper.audience,
                       issuersigningkey = new symmetricsecuritykey(encoding.ascii.getbytes(jwthelper.signingkey))

                       /***********************************tokenvalidationparameters的参数默认值***********************************/
                       // requiresignedtokens = true,
                       // savesignintoken = false,
                       // validateactor = false,
                       // 将下面两个参数设置为false,可以不验证issuer和audience,但是不建议这样做。
                       // validateaudience = true,
                       // validateissuer = true, 
                       // validateissuersigningkey = false,
                       // 是否要求token的claims中必须包含expires
                       // requireexpirationtime = true,
                       // 允许的服务器时间偏移量
                       // clockskew = timespan.fromseconds(300),
                       // 是否验证token有效期,使用当前时间与token的claims中的notbefore和expires对比
                       // validatelifetime = true
                   };
               });

可以看出,jwthelper里的几个变量在startup中也使用了,这样就保证了配置的参数和生成jwt串的参数保持了一致,这样就能起到防伪作用了,不是千千万万个jwt串在咱系统都能通过,如果都通过了,那不是搞笑么。。。

1.3启用验证

public void configure(iapplicationbuilder app, ihostingenvironment env)
        {
            if (env.isdevelopment())
            {
                app.usedeveloperexceptionpage();
            }
        //启用验证
            app.useauthentication();

            //启用验证中间件
            //app.usemiddleware<myautomiddleware>();

            //启用swagger
            app.useswagger();
            app.useswaggerui(options =>
            {
                options.swaggerendpoint("/swagger/v1/swagger.json", "my api v1");

            });

            app.usemvc();
        }

在前一章中,咱们并没有调用app.useauthentication(),是因为上一章咱们自己启用了中间件,并没有启用2.2注入的验证方式。而这一章,咱们注入了jwt,就得调用这句话是执行验证授权了。一旦启用,jwt就会自行进行请求的验证功能,不需要咱们在写代码了。。。

ok,f5运行

我的第一个netcore2.2 api项目搭建(三)

可以看到,未验证,调用失败。。

咱们先用postman调用login模拟登录,生成一个jwt串,代码很简单:

/// <summary>
    /// account 模块
    /// </summary>
    [route("api/[controller]/[action]")]
    [apicontroller]
    public class accountcontroller : controllerbase
    {
        [httpget]
        public actionresult<string> login(long uid, string uname, string sub)
        {
            if (string.isnullorwhitespace(uid.tostring()) || string.isnullorwhitespace(uname)) throw new exception("填写正确用户");

            var tokenstring = jwthelper.createjwttoken(uid.tostring(), uname, sub);

            return tokenstring;
        }
    }

我的第一个netcore2.2 api项目搭建(三)

这里我们得到jwt字符串,将这个字符串添加到header中,再用postman调用get试试:

我的第一个netcore2.2 api项目搭建(三)

headers添加 authorization ,值:bearer +jwt串,在bearer后有个空格记住。

ok了,是不是很简单,到这里jwt简单的认证授权其实已经加完了,后面可以根据各种权限去维护就好了。。。

至此,第三个目标完成!

 既然添加了认证授权,那么第二章swagger部分就得也加入该功能了,这个很简单,只要在swagger里做配置就ok了。

//添加header身份验证信息
                var security = new dictionary<string, ienumerable<string>> { { "bearer", new string[] { } }, };
                options.addsecurityrequirement(security);
                options.addsecuritydefinition("bearer", new apikeyscheme
                {
                    description = "jwt授权(数据将在请求头中进行传输) 参数结构: \"authorization: bearer {token}\"",
                    name = "authorization",//jwt默认的参数名称
                    in = "header",
                    type = "apikey"
                });

f5运行,可以看见加了锁

我的第一个netcore2.2 api项目搭建(三)

点击authorize,然后配置下:

我的第一个netcore2.2 api项目搭建(三)

再来调用get:

我的第一个netcore2.2 api项目搭建(三)

调用成功,可以看到header发送了刚刚添加的jwt串。

至此,整个netcore api项目简单搭建已经完成!

不过,按这种验证写法,突然想到,如果前端被劫持了jwt串,然后其他应用在此jwt串有效期内利用该jwt串调用api,不是也能调通吗??如果这样,不是很危险吗,竟然被别人给瞎调用了,这里留下了深深的思考,不知道大家都是怎么做的。。知情者可否留下解决方式,膜拜!!!