Readdy Write  
0,00 €
Your View Money
Views: Count
Self 20% 0
Your Content 60% 0

Users by Links 0
u1*(Content+Views) 10% 0
Follow-Follower 0
s2*(Income) 5% 0

Count
Followers 0
Login Register as User

Code Sample: Asp Core Web Api und UWP Daten-Client

28.06.2018 (👁32036)


Code-Beispiel: Asp.Net Core Web-API erstellen und mit UWP Client App Daten austauschen unter Verwendung von jwtToken

Beschreibung:

Dieses Code-Beispiel zeigt, wie man in eine Webseite eine Web API (Restful Service) einbaut, mit jwtToken Java Web Tokens den Zugriff und die Übertragung absichert und mit einem UWP Client die Daten liest und bearbeitet.

Begriffe:

UWP Universal Windows Plattform app

JWT Java Web Token

API Application Programming Interface

C# Code

Schritt 1: Voraussetzungen

Asp.Net Core: Api Autorize mit Jwt-Tokens einfügen

Jwt=Java Web Tokens

Vorraussetzungen:

Man muss das Microsoft NuGet Package System IdentityModel Tokens JWT einfügen

Hierzu unter der Asp Solution->Contekt-Menü->Manage Nuget Packages öffnen

Dann in Browse->jwt eingeben

System.IdentityModel.Tokens.Jwt

Includes types that provide support for creating, serializing and validating JSON Web Tokens.

Danach sollte unter Asp.Net Core Project->Dependencies->NuGet

Der Eintrag: System.IdentityModel.Tokens.Jwt stehen

Und zusätzlich die Microsoft.AspNetCore.Authentication.JwtBearer

Microsoft.AspNetCore.Authentication.JwtBearer

ASP.NET Core middleware that enables an application to receive an OpenID Connect bearer token.

 

 

 

Schritt 2: Server TokenController erstellen

Die Datenkommunikation wird über einen Sicherungstoken abgesichert. Hierzu muss die Client-App zunächst einen Sicherheitstoken abholen und diesen in den folgenden Übertragungen als Authorisierung mitübergeben.

Der Sicherheitstoken kann in einem Asp.Net Controller abgeholt werden.

Der Sicherheitstoken enthält einen Schlüssel und ein Gültigkeitsdatum, welcher nur dem Server bekannt ist.

Der Sicherheitstoken wird zu einem UserToken, indem in den Token zusätzliche Informationen eingebaut werden als Claims. Hier wird der User als Claim eingetragen.

Die Claims können dann beim Anfragen von Daten ausgewertet werden und erneut gegen den User geprüft werden.

Durch diese Zusatzinformation Claim.User im Token wird auch später garantiert, dass jeder User nur seine eigenen Daten lesen und schreiben kann.

Token Controller

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

using Microsoft.AspNetCore.Http;

using Microsoft.AspNetCore.Mvc;

 

//< using >

using System.Text;                      //*Encoding

using Microsoft.IdentityModel.Tokens;   //*SymmetricSecurityKey

using System.Security.Claims;           //*Claims for JWT Token

using System.IdentityModel.Tokens.Jwt;  //*JwtRegisteredClaimNames

using Microsoft.Extensions.Primitives;  //StringValues

//</ using >

 

namespace Freelance.Controllers.api

{

    //*when open an api-Connection, first call /api/token and get a valid token to work with the api data

    [Produces("application/json")]

    public class TokenController : Controller

    {

        //--------------< Class: TokenController >---------------------

        //*min 16 chars

        SymmetricSecurityKey _secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Demo_SecretKey_2018-06-27"));

 

 

        [Route("api/get_InitToken")]

        [HttpGet]

        public IActionResult Get_Init_Token()

        {

            //--------< Get_Init_Token >--------

            //--< Create a Token >--

            JwtSecurityToken jwtInitToken = new JwtSecurityToken(

                issuer: "website_freelancer",    //ASP.NET Core web application

                audience: "webclients_freelancer"//client app

                notBefore: DateTime.Now,

                expires: DateTime.Now.AddDays(1),

                signingCredentials: new SigningCredentials(_secretKey, SecurityAlgorithms.HmacSha256)

            );

            //--</ Create a Token >--

 

 

            string stringToken = new JwtSecurityTokenHandler().WriteToken(jwtInitToken);

 

            return Ok(stringToken);

            //--------</ Get_Init_Token() >--------

        }

 

 

 

        [Route("api/get_usertoken")]

        [HttpGet]

        public IActionResult Get_UserToken()

        {

            //-------------< Get_UserToken() >------------- 

            //*Create a Usertoken if parameters are correct.

 

 

            string username = "";

            string password = "";

 

            if (Request.Headers.TryGetValue("Authorization"out StringValues authToken))

            {

                string authHeader = authToken.First();

                string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim();

                Encoding encoding = Encoding.UTF8; 

                string usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword));

                int seperatorIndex = usernamePassword.IndexOf(':');

                username = usernamePassword.Substring(0, seperatorIndex);

                password = usernamePassword.Substring(seperatorIndex + 1);

            }

            else

            {

                return BadRequest("Missing Authorization Header.");

            }

 

 

 

 

 

            //*check here against user and password

            if (check_login_user_password(username,password) == true)

            {

                //< login ok >

                string sToken = create_UserToken(username);

                return Content(sToken);

                //</ login ok >

            }

            else

            {

                //< login failed >

                return BadRequest();

                //</ login failed >

            }

 

            //-------------</ Get_UserToken() >------------- 

        }

 

 

 

        //*reference: www.blinkingcaret.com

        public string create_UserToken(string sUsername)

        {

            //-------------< create_UserToken() >-------------

            Claim[] claims = new Claim[] {

                new Claim(ClaimTypes.Name, sUsername), //*->User.Identity.Name or "Raimund Popp"

                new Claim(JwtRegisteredClaimNames.Email, "raimund.popp@codedocu.de")

 

            };

 

 

            //--< Create a Token >--

            JwtSecurityToken jwtToken = new JwtSecurityToken(

                issuer: "website_freelancer",    //ASP.NET Core web application

                audience: "webclients_freelancer"//client app

                claims: claims,

                notBefore: DateTime.Now,

                expires: DateTime.Now.AddDays(1),

                signingCredentials: new SigningCredentials(_secretKey, SecurityAlgorithms.HmacSha256)

            );

            //--</ Create a Token >--

 

 

            string stringToken = new JwtSecurityTokenHandler().WriteToken(jwtToken);

 

            return stringToken;

            //-------------</ create_UserToken() >-------------

        }

 

 

 

 

        private bool check_login_user_password(string sUsername, string sPassword)

        {

            //-------------< check_login_user_password() >-------------

            //#todo: check user and password from user.

            return true;

            //-------------</ check_login_user_password() >-------------

        }

        //--------------</ Class: TokenController >---------------------

    }

}

 

 

 

 

Schritt 3: WebApi Authorisieren

 

Web API Controller

Wenn der Client später seine Daten abholen oder schreiben möchte, dann wechselt dieser zum WebApi-Controller.

Dieser WebApi Controller befindet sich in der Regel in einem Unterverzeichnis /Api.

Zu Beginn des Controller-Aufrufs wird der Zugriff auf den WebApi Controller geprüft, indem die Authorizierung vorgeschaltet wird.

Hierzu ist das Attribute: Authorize mit dem Schema JwtBearer einzufügen

[Authorize(AuthenticationSchemes = "JwtBearer")]    

WebApi Controller: Api/ProjectsController

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

using Freelance.Data;

using Freelance.Models;

using Microsoft.AspNetCore.Authorization;

using Microsoft.AspNetCore.Http;

using Microsoft.AspNetCore.Mvc;

 

 

namespace Freelance.Controllers.api

{

    [Authorize(AuthenticationSchemes = "JwtBearer")]    //*goes to startup ConfigureServices.AddAuthentication->AddJwtBearer(..)

    [Produces("application/json")]

    [Route("api/Projects")]

    public class ProjectsController : Controller

    {

        //--------------< Class: ApiController >---------------------

        #region Controller Init

        private readonly ApplicationDbContext _dbContext;

        

        public ProjectsController(ApplicationDbContext dbContext)

        {

            //----< Init: Controller >----

            _dbContext = dbContext;

            //----</ Init: Controller >----

        }

        #endregion

 

 

        // GET: /api/index

        //[Authorize]

        public List<ProjectModel> Index()

        {

            ///-------------< Index >------------- 

 

            //--< Get Linq.Query >--

            //*gets last 10 Projects with View_Sum

            var query = (from n in _dbContext.tbl_Projects

                         where n.IsDraft == false

                         orderby n.IDProject descending

                         select  n ).Take(10);

            //--</ Get Linq.Query >--

 

            //----< fill Data_to_View >----

            List<ProjectModel> dataList = query.ToList<ProjectModel>();

         

            //< out >

            //*output to client

            return dataList;

            //</ out >

            ///-------------</ Index >------------- 

        }

       //--------------</ Class: ApiController  >---------------------

    }

}

Schritt 5: Authorisierung Service einfügen

Wenn eine Client Anwendung eine Wep API (REST Service) öffnen möchte, dann führt das Attribute: Authorize im Controller eine Prüfung durch.

[Authorize(AuthenticationSchemes = "JwtBearer")]    

Die Prüfung muss als Schema in der Asp.Net Core Startup Datei eingefügt werden im Bereich Configure Services

//----< JWT-Token >----

            //*reference: www.blinkingcaret.com

            services.AddAuthentication(options =>

            {

                options.DefaultAuthenticateScheme = "JwtBearer";

                options.DefaultChallengeScheme = "JwtBearer";

            })

 

            .AddJwtBearer("JwtBearer", jwtBearerOptions =>

            {

                jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters

                {

                    ValidateIssuerSigningKey = true,

                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Demo_SecretKey_2018-06-27")),

 

                    ValidateIssuer = true,

                    ValidIssuer = "website_freelancer",

 

                    ValidateAudience = true,

                    ValidAudience = "webclients_freelancer",

 

                    ValidateLifetime = true//validate the expiration and not before values in the token

 

                    ClockSkew = TimeSpan.FromMinutes(5) //5 minute tolerance for the expiration date

                };

            });

            //----</ JWT-Token >----

Sowie im Startup Block Configure muss die Authorisierung generell aktiveriert werden

            app.UseAuthentication();

Startup.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

using Microsoft.AspNetCore.Builder;

using Microsoft.AspNetCore.Identity;

using Microsoft.EntityFrameworkCore;

using Microsoft.AspNetCore.Hosting;

using Microsoft.Extensions.Configuration;

using Microsoft.Extensions.DependencyInjection;

using Freelance.Data;

using Freelance.Models;

using Freelance.Services;

using Microsoft.AspNetCore.Rewrite;

using Microsoft.AspNetCore.Http;

using Microsoft.IdentityModel.Tokens;   //*TokenValidationParameters

using System.Text;                      //*Encoding

 

namespace Freelance

{

    public class Startup

    {

 

 

        public Startup(IHostingEnvironment env)

        {

            var builder = new ConfigurationBuilder();

            builder.AddUserSecrets<Startup>();

 

            Configuration = builder.Build();

        }

 

        public IConfiguration Configuration { get; }

 

        // This method gets called by the runtime. Use this method to add services to the container.

        public void ConfigureServices(IServiceCollection services)

        {

            //-----------< ConfigureServices()  >-----------

            //Website_Constants.Connectionstring = Configuration["DefaultConnection"].ToString();

 

 

            services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Website_Constants.Connectionstring));

            //--< Identity >--

            services.AddIdentity<ApplicationUserIdentityRole>(config =>

            {

                //< send Register Email >

                //*prevents registered users from logging in until their email is confirmed.

                config.SignIn.RequireConfirmedEmail = true;

                //</ send Register Email >

            })

            .AddEntityFrameworkStores<ApplicationDbContext>()

            .AddDefaultTokenProviders();

            //--</ Identity >--

 

            //----< JWT-Token >----

            //*reference: www.blinkingcaret.com

            services.AddAuthentication(options =>

            {

                options.DefaultAuthenticateScheme = "JwtBearer";

                options.DefaultChallengeScheme = "JwtBearer";

            })

 

            .AddJwtBearer("JwtBearer", jwtBearerOptions =>

            {

                jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters

                {

                    ValidateIssuerSigningKey = true,

                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Demo_SecretKey_2018-06-27")),

 

                    ValidateIssuer = true,

                    ValidIssuer = "website_freelancer",

 

                    ValidateAudience = true,

                    ValidAudience = "webclients_freelancer",

 

                    ValidateLifetime = true//validate the expiration and not before values in the token

 

                    ClockSkew = TimeSpan.FromMinutes(5) //5 minute tolerance for the expiration date

                };

            });

            //----</ JWT-Token >----

 

            // Add application services.

            services.AddTransient<IEmailSenderEmailSender>();

 

            var optRewrite = new RewriteOptions()

            .AddRedirectToHttpsPermanent();

 

 

            services.AddMvc();

 

            //-----------</ ConfigureServices() >-----------

        }

 

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)

        {

            //-----------< Configure() >-----------

            if (env.IsDevelopment())

            {

                app.UseBrowserLink();

                app.UseDeveloperExceptionPage();

                app.UseDatabaseErrorPage();

            }

            else

            {

                app.UseExceptionHandler("/Home/Error");

            }

 

            app.UseStaticFiles();

 

            app.UseAuthentication();

 

            app.UseMvc(routes =>

            {

 

 

 

                //--< Emoticons >--

                routes.MapRoute(

                   name: "🏠",

                   template: "🏠",

                   defaults: new { controller = "Home", action = "Index" }

               );

                routes.MapRoute(

                name: "📢",

                template: "📢",

                defaults: new { controller = "Home", action = "Index" }

                );

                routes.MapRoute(

                   name: "📜",

                   template: "📜",

                   defaults: new { controller = "Projects", action = "Index_all" }

                );

                //--</ Emoticons >--

 

                routes.MapRoute(

                   name: "Projects"// Route name

                   template: "Projects"// URL with parameters

                   defaults: new { controller = "Projects", action = "Index_all" }

               );

 

 

 

                routes.MapRoute(

                    name: "default",

                    template: "{controller=Projects}/{action=Index_all}/{id?}");

 

            }

            );

 

 

            //seed dbContext 

            Database.EF_Model.Initialize_DbContext_in_Startup(app.ApplicationServices);

            //-----------</ Configure()  >-----------

        }

    }

}

 

 

Schritt 6: Client Zugriff

Hier am Beispiel eines UWP Clients

Client: UWP Client

Der Client holt sich im ersten Schritt einen User-Token ab. Diesen Token erhält er vom Server unter /api/get_usertoken.

Hierzu kann man den User und Passwort initial übertragen, damit in den UserToken der User als Claim-Information eingetragen wird.

            //-< get user token >-

            //*get the User-Password valid token 

            string sURL_Login = "http://localhost:51198/api/get_usertoken";

            var byteArray = Encoding.UTF8.GetBytes("MyUSER:MyPASS");

            var header = new AuthenticationHeaderValue("Basic"Convert.ToBase64String(byteArray));

            client.DefaultRequestHeaders.Authorization = header;

 

            string sUserToken = await client.GetStringAsync(sURL_Login);

            //-< get user token >-

Anschliessend kann der Client mit diesem UserToken seine eigenen Daten mit dem Web API Controller (REST Services) holen, lesen und bearbeiten.

//< read webApi >

            string sURL = "http://localhost:51198/api/projects";

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", sUserToken);

            string sResponse_Projects = "";

            try

            {

                sResponse_Projects = await client.GetStringAsync(sURL);

            }

            catch (Exception ex)

            {

                string sMessage = ex.InnerException.ToString();

                MessageDialog dialog = new MessageDialog(sMessage, "Information");

                await dialog.ShowAsync();

                return;

            }

            //</ read webApi >

 

 

 

Client Code

using System;

using System.Net;

using System.Net.Http;          //*HttpClient

using System.Net.Http.Headers;  //*AuthenticationHeaderValue

using System.Text;              //*Encoding

using Windows.Data.Json;        //*JsonObject

using Windows.UI.Popups;

using Windows.UI.Xaml;

using Windows.UI.Xaml.Controls;

 

 

namespace api01

{

 

    public sealed partial class MainPage : Page

    {

        public MainPage()

        {

            this.InitializeComponent();

        }

 

        private void btnStart_Click(object sender, RoutedEventArgs e)

        {

            read_API_Data();

 

        }

 

 

        public async void read_API_Data()

        {

            //---------------< read_API_Data() >---------------

 

            HttpClient client = new HttpClient();

 

            //-< get init token >-

            //*plain init-Token

            //string sURL_Login = "http://localhost:51198/api/get_InitToken";

            //string sToken = await client.GetStringAsync(sURL_Login);

            //-</ get init token >-

 

 

            //-< get user token >-

            //*get the User-Password valid token 

            string sURL_Login = "http://localhost:51198/api/get_usertoken";

            var byteArray = Encoding.UTF8.GetBytes("MyUSER:MyPASS");

            var header = new AuthenticationHeaderValue("Basic"Convert.ToBase64String(byteArray));

            client.DefaultRequestHeaders.Authorization = header;

 

            string sUserToken = await client.GetStringAsync(sURL_Login);

            //-< get user token >-

 

 

            //< read webApi >

            string sURL = "http://localhost:51198/api/projects";

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", sUserToken);

            string sResponse_Projects = "";

            try

            {

                sResponse_Projects = await client.GetStringAsync(sURL);

            }

            catch (Exception ex)

            {

                string sMessage = ex.InnerException.ToString();

                MessageDialog dialog = new MessageDialog(sMessage, "Information");

                await dialog.ShowAsync();

                return;

            }

            //</ read webApi >

 

            

            //< get Json values >

            JsonArray jsonArray = JsonArray.Parse(sResponse_Projects);

            foreach (var jsonRow in jsonArray)

            {

                //----< json Row >----

                JsonObject jsonObject=jsonRow.GetObject();

 

                //< values >

                string IDProject= jsonObject["idProject"].ToString();

                string Title = jsonObject["title"].ToString();

                string Text = jsonObject["text"].ToString();

                string dtEdit = jsonObject["dtEdit"].ToString();

                //</ values >

 

                tbxResults.Text += Environment.NewLine + "-------";

                tbxResults.Text += Environment.NewLine + "idProject=" + IDProject;

                tbxResults.Text += Environment.NewLine + "Title=" + Title;

                tbxResults.Text += Environment.NewLine + "Text=" + Text;

                tbxResults.Text += Environment.NewLine + "dtEdit=" + dtEdit;

                //----</ json Row >----

            }

 

            //</ get Json values >

            //---------------</ read_API_Data() >---------------

        }

 

 

    }

}