portaldacalheta.pt
  • Главни
  • Иновација
  • Алати И Упутства
  • Укс Дизајн
  • Рисе Оф Ремоте
Бацк-Енд

Како се врши ЈВТ аутентификација помоћу Ангулар 6 СПА



Данас ћемо погледати како је лако интегрисати ЈСОН веб токен (ЈВТ) аутентичност у ваш Угаона 6 (или новија) ​​апликација на једној страници (СПА). Почнимо са мало позадине.

Шта су ЈСОН веб жетони и зашто их користити?

Овде је најлакши и најсажетији одговор да су прикладни, компактни и сигурни. Погледајмо те тврдње детаљно:



  1. Погодно : Коришћење ЈВТ за аутентификацију на задњем крају након што се пријавите захтева постављање једног ХТТП заглавља, задатак који се лако може аутоматизовати помоћу функције или поткласирања, као што ћемо видети касније.
  2. Компактан : Токен је једноставно низ кодиран основом 64, садржи неколико поља заглавља и корисни терет ако је потребно. Укупни ЈВТ је обично мањи од 200 бајтова, чак и ако је потписан.
  3. Сигурно : Иако није потребно, одлична сигурносна карактеристика ЈВТ-а је та што се токени могу потписати користећи РСА јавно / приватно шифрирање пара кључева или ХМАЦ шифрирање користећи заједничку тајну. Ово осигурава порекло и валидност токена.

На шта се све ово своди је да имате сигуран и ефикасан начин за аутентификацију корисника, а затим верификацију позива на ваше АПИ крајње тачке без потребе за рашчлањивањем било каквих структура података нити за применом сопствене енкрипције.



Теорија примене

Типичан проток података за ЈВТ аутентификацију и употребу између фронт-енд и бацк-енд система



Дакле, са мало позадине, сада можемо заронити у то како би ово функционисало у стварној апликацији. За овај пример претпоставићу да имамо Ноде.јс сервер који хостује наш АПИ, а ми јесмо развијање СПА све листе користе Угаона 6. Хајде да радимо и са овом АПИ структуром:

предности вештачке интелигенције
  • /auth → POST (објавите корисничко име и лозинку за потврду идентитета и примање ЈВТ-а)
  • /todos → GET (вратите листу свих ставки листе корисника)
  • /todos/{id} → GET (вратите одређену ставку листе задатака)
  • /users → GET (враћа листу корисника)

Ускоро ћемо проћи кроз стварање ове једноставне апликације, али за сада се концентришимо на интеракцију у теорији. Имамо једноставну страницу за пријављивање, где корисник може да унесе своје корисничко име и лозинку. Када се образац преда, он шаље те информације на /auth крајња тачка. Ноде сервер тада може да аутентификује корисника на било који начин који одговара (тражење базе података, постављање упита другој веб услузи итд.), Али на крају крајња тачка мора да врати ЈВТ.



ЈВТ за овај пример садржи неколико резервисана потраживања , а неки приватна потраживања . Резервисана потраживања су једноставно парови кључ / вредност које препоручује ЈВТ, а који се обично користе за потврду идентитета, док су приватна потраживања парови парови кључ / вредност применљиви само на нашу апликацију:

Резервисани захтеви



  • iss: Издавач овог токена. Типично је ФКДН сервера, али може бити било шта све док клијентска апликација зна да то очекује.
  • exp: Датум и време истека овог токена. Ово је у секундама од поноћи 01. јануара 1970 ГМТ (Уник време).
  • nbf: Не важи пре временске ознаке. Не користи се често, али даје доњу границу за период важења. Исти формат као exp.

Приватни захтеви

  • uid: Усер ИД пријављеног корисника.
  • role: Улога додељена пријављеном кориснику.

Наше информације ће бити кодиране у основи 64 и потписане помоћу ХМАЦ-а заједничким кључем todo-app-super-shared-secret. Испод је пример како ЈВТ изгледа:



eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0b2RvYXBpIiwibmJmIjoxNDk4MTE3NjQyLCJleHAiOjE0OTgxMjEyNDIsInVpZCI6MSwicm9sZSI6ImFkbWluIn0.ZDz_1vcIlnZz64nSM28yA1s-4c_iw3Z2ZtP-SgcYRPQ

Ово стринг је све што нам је потребно да бисмо били сигурни да имамо ваљану пријаву, да бисмо знали који је корисник повезан и да бисмо знали чак и које улоге корисник има.

Већина библиотека и апликација наставља да складишти овај ЈВТ у localStorage или sessionStorage за лако проналажење, али ово је само уобичајена пракса. Шта ћете радити са токеном, зависи од вас, под условом да га можете обезбедити за будуће АПИ позиве.



Сада, кад год СПА жели да упути позив било којој од заштићених крајњих тачака АПИ-ја, једноставно мора да пошаље токен у Authorization ХТТП заглавље.

Authorization: Bearer {JWT Token}

Белешка : Још једном, ово је једноставно уобичајена пракса. ЈВТ не прописује ниједан одређени метод за само слање на сервер. Можете га додати и УРЛ-у или послати у колачићу.



Једном када сервер прими ЈВТ, он га може декодирати, осигурати доследност користећи заједничку тајну ХМАЦ-а и проверити истек помоћу exp и nbf поља. Такође може користити iss поље како би се осигурало да је првобитна издавалачка страна овог ЈВТ-а.

Једном када се сервер задовољи ваљаношћу токена, могу се користити информације ускладиштене унутар ЈВТ-а. На пример, uid који смо укључили даје нам ИД корисника који подноси захтев. За овај конкретни пример такође смо укључили role поље, које нам омогућава да доносимо одлуке о томе да ли корисник треба да може да приступи одређеној крајњој тачки или не. (Да ли верујете овим информацијама или радије желите да претражите базу података зависи од потребног нивоа сигурности.)

function getTodos(jwtString) { var token = JWTDecode(jwtstring); if( Date.now() token.exp*1000) { throw new Error('Token has expired'); } if( token.iss != 'todoapi') { throw new Error('Token not issued here'); } var userID = token.uid; var todos = loadUserTodosFromDB(userID); return JSON.stringify(todos); }

Направимо једноставну апликацију Тодо

Да бисте наставили даље, мораћете да имате инсталирану новију верзију Ноде.јс (6.к или новија), нпм (3.к или новија) ​​и ангулар-цли. Ако требате да инсталирате Ноде.јс, који укључује нпм, следите упутства овде . После angular-cli може се инсталирати помоћу npm (или yarn, ако сте га инсталирали):

# installation using npm npm install -g @angular/cli # installation using yarn yarn global add @angular/cli

Нећу улазити у детаље о узорку Ангулар 6 који ћемо овде користити, али за следећи корак сам створио спремиште Гитхуб у којем се налази мала тодо апликација која илуструје једноставност додавања ЈВТ потврде идентитета у вашу апликацију. Једноставно га клонирајте користећи следеће:

git clone https://github.com/sschocke/angular-jwt-todo.git cd angular-jwt-todo git checkout pre-jwt

Тхе git checkout pre-jwt наредба се пребацује на именовано издање тамо гдје ЈВТ није имплементиран.

Унутар би требало да постоје две фасцикле под називом server и client. Сервер је Ноде АПИ сервер који ће угостити наш основни АПИ. Клијент је наша апликација Ангулар 6.

Ноде АПИ Сервер

Да бисте започели, инсталирајте зависности и покрените АПИ сервер.

cd server # installation using npm npm install # or installation using yarn yarn node app.js

Требали бисте бити у могућности да пратите ове везе и добијете ЈСОН представу података. За сада, док нисмо проверили идентитет, чврсто смо кодирали /todos крајња тачка за враћање задатака за userID=1:

како се користи шаблон за покретање
  • хттп: // лоцалхост: 4000 / : Тестирајте страницу да бисте видели да ли је покренут Ноде сервер
  • хттп: // лоцалхост: 4000 / апи / усерс : Повратак на списак корисника у систему
  • хттп: // лоцалхост: 4000 / апи / алл : Повратак на листу задатака за userID=1

Тхе Ангулар Апп

Да бисмо започели са клијентском апликацијом, такође морамо инсталирати зависности и покренути дев сервер.

cd client # using npm npm install npm start # using yarn yarn yarn start

Белешка : У зависности од брзине ваше линије, потребно је неко време да преузмете све зависности.

Ако све иде како треба, требало би да видите нешто слично приликом навигације до хттп: // лоцалхост: 4200 :

Верзија наше апликације Ангулар Тодо Лист која не подржава ЈВТ.

Додавање аутентификације путем ЈВТ-а

Да бисмо додали подршку за ЈВТ аутентификацију, користићемо неке стандардне библиотеке које то чине једноставнијим. Можете се, наравно, одрећи ових погодности и све применити сами, али то је изван нашег делокруга овде.

Прво, инсталирајмо библиотеку на страни клијента. Развио га је и одржава Аутх0 , која је библиотека која вам омогућава додавање аутентичност заснована на облаку на веб локацију. Коришћење саме библиотеке не захтева да користите њихове услуге.

cd client # installation using npm npm install @auth0/angular-jwt # installation using yarn yarn add @auth0/angular-jwt

Доћи ћемо до кода за секунду, али док смо већ код тога, подесимо и серверску страну. Користићемо body-parser, jsonwebtoken и express-jwt библиотеке како би Ноде разумео ЈСОН ПОСТ тела и ЈВТ-ове.

cd server # installation using npm npm install body-parser jsonwebtoken express-jwt # installation using yarn yarn add body-parser jsonwebtoken express-jwt

АПИ крајња тачка за потврду идентитета

Прво, потребан нам је начин за аутентификацију корисника пре него што им дамо токен. За наш једноставан демо, поставићемо само фиксну крајњу тачку за потврду идентитета са чврсто кодираним корисничким именом и лозинком. Ово може бити једноставно или сложено колико захтева ваша апликација. Важно је послати ЈВТ.

У server/app.js додајте унос испод другог require редови како следи:

const bodyParser = require('body-parser'); const jwt = require('jsonwebtoken'); const expressJwt = require('express-jwt');

Као и следеће:

app.use(bodyParser.json()); app.post('/api/auth', function(req, res) { const body = req.body; const user = USERS.find(user => user.username == body.username); if(!user || body.password != 'todo') return res.sendStatus(401); var token = jwt.sign({userID: user.id}, 'todo-app-super-shared-secret', {expiresIn: '2h'}); res.send({token}); });

Ово је углавном основни ЈаваСцрипт код. Добијамо ЈСОН тело које је прослеђено у /auth крајњу тачку, пронађите корисника који се подудара с тим корисничким именом, проверите да ли се корисник и лозинка подударају и вратите 401 Unauthorized ХТТП грешка ако није.

Важан део је генерација токена и то ћемо рашчланити по три параметра. Синтакса за sign је следећи: jwt.sign(payload, secretOrPrivateKey, [options, callback]), где:

  • payload је литерарни објекат парова кључ / вредност који желите да кодирате у оквиру свог токена. Те информације тада може декодирати из токена свако ко има кључ за дешифровање. У нашем примеру кодирамо user.id тако да када поново примимо токен на задњем крају ради потврде идентитета, знамо са којим корисником имамо посла.
  • secretOrPrivateKey је или дељени тајни кључ ХМАЦ шифровања - ово је оно што смо ради једноставности користили у нашој апликацији или приватни кључ РСА / ЕЦДСА енкрипције.
  • options представља низ опција које се могу проследити кодеру у облику парова кључ / вредност. Обично наводимо најмање expiresIn (постаје exp резервисана тужба) и issuer (iss резервисано полагање права) тако да токен не важи заувек, а сервер може да провери да ли је токен у ствари првобитно издао.
  • callback је функција коју треба позвати након завршетка кодирања, уколико неко жели асинхроно руковати кодирањем токена.

(Такође можете читати о више детаља о options и како се користи криптографија јавног кључа уместо заједничког тајног кључа .)

Угаона 6 ЈВТ интеграција

Направити Ангулар 6 да ради са нашим ЈВТ-ом прилично је једноставно користећи angular-jwt. Једноставно додајте следеће у client/src/app/app.modules.ts:

import { JwtModule } from '@auth0/angular-jwt'; // ... export function tokenGetter() { return localStorage.getItem('access_token'); } @NgModule({ // ... imports: [ BrowserModule, AppRoutingModule, HttpClientModule, FormsModule, // Add this import here JwtModule.forRoot({ config: { tokenGetter: tokenGetter, whitelistedDomains: ['localhost:4000'], blacklistedRoutes: ['localhost:4000/api/auth'] } }) ], // ... }

То је у основи све што је потребно. Наравно, морамо додати још кода за почетну аутентификацију, али angular-jwt библиотека брине о слању токена уз сваки ХТТП захтев.

  • Тхе tokenGetter() функција ради тачно оно што каже, али како ће се применити зависи само од вас. Одлучили смо да вратимо токен који смо сачували у localStorage. Слободни сте да наведете било који други начин који желите, све док он враћа ЈСОН веб токен кодирани низ.
  • Тхе whiteListedDomains опција постоји, тако да можете ограничити на које домене се ЈВТ шаље, тако да јавни АПИ-ји неће примати и ваш ЈВТ.
  • Тхе blackListedRoutes опција вам омогућава да одредите одређене руте које не би требале да приме ЈВТ, чак и ако су на домену са беле листе. На пример, крајња тачка за потврду идентитета не треба да је прими јер нема смисла: токен је ионако нулан када се ионако позове.

Све то заједно

У овом тренутку имамо начин да генеришемо ЈВТ за датог корисника помоћу /auth крајњу тачку на нашем АПИ-ју, а водовод смо обавили на Ангулар-у за слање ЈВТ-а са сваким ХТТП захтевом. Одлично, али могли бисте да нагласите да се апсолутно ништа није променило за корисника. И били бисте у праву. И даље можемо доћи до сваке странице у нашој апликацији и можемо позвати било коју крајњу тачку АПИ-ја, а да чак ни не пошаљемо ЈВТ. Није добро!

колико принципа дизајна постоји

Морамо да ажурирамо нашу клијентску апликацију да бисмо били забринути ко је пријављен, а такође и наш АПИ да захтева ЈВТ. Хајде да почнемо.

За пријављивање ће нам бити потребна нова компонента Ангулар. Ради краткоће, учинићу ово што једноставнијим. Такође ће нам требати услуга која ће се бавити свим нашим захтевима за потврду идентитета и Угаона гарда да бисмо заштитили руте којима не би требало да буду доступне пре пријављивања. Урадићемо следеће у контексту клијентске апликације.

cd client ng g component login --spec=false --inline-style ng g service auth --flat --spec=false ng g guard auth --flat --spec=false

Ово је требало генерисати четири нове датотеке у client директоријум:

src/app/login/login.component.html src/app/login/login.component.ts src/app/auth.service.ts src/app/auth.guard.ts

Даље, морамо да пружимо услугу потврде идентитета и заштиту наше апликације. Ажурирање client/src/app/app.modules.ts:

import { AuthService } from './auth.service'; import { AuthGuard } from './auth.guard'; // ... providers: [ TodoService, UserService, AuthService, AuthGuard ],

А затим ажурирајте рутирање у client/src/app/app-routing.modules.ts да бисте користили заштитник за аутентификацију и обезбедили руту за компоненту за пријаву.

// ... import { LoginComponent } from './login/login.component'; import { AuthGuard } from './auth.guard'; const routes: Routes = [ { path: 'todos', component: TodoListComponent, canActivate: [AuthGuard] }, { path: 'users', component: UserListComponent, canActivate: [AuthGuard] }, { path: 'login', component: LoginComponent}, // ...

На крају, ажурирајте client/src/app/auth.guard.ts са следећим садржајима:

import { Injectable } from '@angular/core'; import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; @Injectable() export class AuthGuard implements CanActivate { constructor(private router: Router) { } canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) { if (localStorage.getItem('access_token')) { return true; } this.router.navigate(['login']); return false; } }

За нашу демо апликацију једноставно проверавамо да ли постоји ЈВТ у локалном складишту. У стварним апликацијама декодирали бисте токен и проверили његову ваљаност, истек итд. На пример, могли бисте да користите ЈвтХелперСервице за ово.

У овом тренутку, наша апликација Ангулар сада ће вас увек преусмерити на страницу за пријављивање, јер ми не можемо да се пријавимо. Исправимо то, почевши од услуге потврде идентитета у client/src/app/auth.service.ts:

import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Injectable() export class AuthService { constructor(private http: HttpClient) { } login(username: string, password: string): Observable { return this.http.post('/api/auth', {username: username, password: password}) .pipe( map(result => { localStorage.setItem('access_token', result.token); return true; }) ); } logout() { localStorage.removeItem('access_token'); } public get loggedIn(): boolean { return (localStorage.getItem('access_token') !== null); } }

Наша услуга потврде идентитета има само две функције, login и logout:

  • login POST с обезбеђеним username и password на наш задњи крај и поставља access_token у localStorage ако прими један назад. Ради једноставности, овде нема руковања грешкама.
  • logout једноставно брише access_token од localStorage, захтевајући да се набави нови токен пре него што се поново може приступити било чему другом.
  • loggedIn је логичко својство помоћу којег можемо брзо утврдити да ли је корисник пријављен или није.

И на крају, компонента за пријаву. Они немају никакве везе са стварним радом са ЈВТ-ом, зато слободно копирајте и залепите у client/src/app/login/login.components.html:

{{error}}

Username Password Login

И client/src/app/login/login.components.ts требаће:

import { Component, OnInit } from '@angular/core'; import { AuthService } from '../auth.service'; import { Router } from '@angular/router'; import { first } from 'rxjs/operators'; @Component({ selector: 'app-login', templateUrl: './login.component.html' }) export class LoginComponent { public username: string; public password: string; public error: string; constructor(private auth: AuthService, private router: Router) { } public submit() { this.auth.login(this.username, this.password) .pipe(first()) .subscribe( result => this.router.navigate(['todos']), err => this.error = 'Could not authenticate' ); } }

Ето, наш пример пријаве за Ангулар 6:

Екран за пријаву узорка апликације Ангулар Тодо Лист.

У овој фази требали бисмо бити у могућности да се пријавимо (користећи jemma, paul или sebastian са лозинком todo) и поново видите све екране. Али наша апликација показује иста заглавља за навигацију и нема начина да се одјавите без обзира на тренутно стање. Поправимо то пре него што пређемо на поправљање нашег АПИ-ја.

У client/src/app/app.component.ts, замените целу датотеку следећим:

import { Component } from '@angular/core'; import { Router } from '@angular/router'; import { AuthService } from './auth.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { constructor(private auth: AuthService, private router: Router) { } logout() { this.auth.logout(); this.router.navigate(['login']); } }

И за client/src/app/app.component.html замените овај одељак следећим:

Todo List Users Login Logout

Уверили смо контекст наше навигације да би требало да приказује само одређене ставке у зависности од тога да ли је корисник пријављен или не. auth.loggedIn може се, наравно, користити било где где можете да увезете услугу потврде идентитета.

Обезбеђивање АПИ-ја

Можда размишљате, ово је сјајно ... изгледа да све делује предивно . Али покушајте да се пријавите са сва три различита корисничка имена и приметићете нешто: Сви они враћају исту листу задатака. Ако погледамо наш АПИ сервер, можемо видети да сваки корисник у ствари има своју листу ставки, па шта има?

Па, запамтите када смо започели, кодирали смо наш /todos Крајња тачка АПИ-ја да увек врати списак задатака за userID=1. То је било зато што нисмо имали начина да сазнамо ко је тренутно пријављени корисник.

Сада то радимо, па да видимо како је лако осигурати своје крајње тачке и користити информације кодиране у ЈВТ-у за пружање потребног корисничког идентитета. У почетку додајте овај један ред у свој server/app.js датотека тачно испод последњег app.use() позив:

app.use(expressJwt({secret: 'todo-app-super-shared-secret'}).unless({path: ['/api/auth']}));

Користимо express-jwt миддлеваре, реците му шта је дељена тајна и наведите низ путања за које не би требало да захтева ЈВТ. И то је то. Нема потребе да додирујете сваку крајњу тачку, направите if изјаве свуда или било шта друго.

Интерни софтвер интервенира износи неколико претпоставки. На пример, претпоставља Authorization ХТТП заглавље следи уобичајени ЈВТ образац од Bearer {token}. (Библиотека, међутим, има пуно опција за прилагођавање њеног рада, ако то није случај. Погледајте екпресс-јвт Употреба За више детаља.)

Наш други циљ је да користимо информације кодиране ЈВТ-ом да бисмо сазнали ко упућује позив. Још једном express-jwt долази у помоћ. Као део читања токена и његове верификације, он поставља кодирану корисну тежину коју смо послали у процесу потписивања на променљиву req.user у Екпресс-у. Тада га можемо користити за тренутни приступ било којој променљивој коју смо сачували. У нашем случају постављамо userID једнак идентификованом ИД-у корисника и као такав га можемо користити директно као req.user.userID.

Ажурирање server/app.js поново и промените /todos крајња тачка да гласи како следи:

res.send(getTodos(req.user.userID));

Наша апликација Угаона листа задатака користи ЈВТ за приказ листе задатака пријављеног корисника, а не оне коју смо раније кодирали.

И то је то. Наш АПИ је сада заштићен од неовлашћеног приступа и можемо сигурно утврдити ко је наш аутентификовани корисник у било којој крајњој тачки. Наша клијентска апликација такође има једноставан поступак потврде идентитета, а све ХТТП услуге које напишемо и које позивају нашу АПИ крајњу тачку аутоматски ће имати приложен токен за потврду идентитета.

дизајнери огласа користе кретање како би

Ако сте клонирали Гитхуб спремиште и једноставно желите да видите крајњи резултат на делу, код можете погледати у коначном облику користећи:

git checkout with-jwt

Надам се да вам је ово упутство драгоцено за додавање ЈВТ аутентификација у своје Ангулар апликације. Хвала за читање!

Повезан: Водич за ЈСОН веб токене: Пример у Ларавел-у и АнгуларЈС-у

Разумевање основа

Шта је жетон у програмирању?

У програмском смислу, токен има много дефиниција. Што се тиче безбедности и аутентификације, то је једноставно непрозирни низ који кодира малу количину информација које се лако могу пренети и сачувати, али са готово нула шанси за колизије са било којим другим токеном.

Шта је токен-аутентификација?

Аутентификација заснована на токенима једноставно значи кодирање података потребних за аутентификацију и ауторизацију корисника у токен, а затим коришћење тог необавезно криптографски потписаног токена за ауторизацију уместо комбинација корисничког имена / лозинке приликом приступа заштићеним ресурсима.

Шта је ЈВТ у Јави?

ЈВТ је скраћеница за ЈСОН Веб Токен, што у основи значи да је то ЈСОН објекат са заглављем, корисним оптерећењем и потписом. Представља сигуран начин размене информација о аутентификацији између две стране преко мреже када се користе заједно са другим технологијама попут ССЛ-а.

Шта је ОАутх 2.0?

ОАутх 2.0 је стандардни протокол за извођење ауторизације на великом броју подржаних платформи. На пример, Гоогле, Фацебоок и ОпенИД користе ОАутх 2.0. Дефинише кораке и формат који треба следити за аутентификацију помоћу датог сервера за потврду идентитета и добијање приступа заштићеним ресурсима.

Крипто валута за почетнике: Битцоин и даље

Наука О Подацима И Базе Података

Крипто валута за почетнике: Битцоин и даље
Представите своје вештине - Како направити портфељ

Представите своје вештине - Како направити портфељ

Укс Дизајн

Популар Постс
Начело појединачне одговорности: рецепт за велики кодекс
Начело појединачне одговорности: рецепт за велики кодекс
Зашто размотрити редизајн веб странице - савети и препоруке
Зашто размотрити редизајн веб странице - савети и препоруке
Поуке из инвестиционе стратегије Варрена Буффетта и његове грешке
Поуке из инвестиционе стратегије Варрена Буффетта и његове грешке
Осам правила за ефикасну производњу софтвера
Осам правила за ефикасну производњу софтвера
Стварање нарације од бројева
Стварање нарације од бројева
 
Виши технички регрут
Виши технички регрут
Управљање удаљеним слободњацима? Ови принципи ће вам помоћи
Управљање удаљеним слободњацима? Ови принципи ће вам помоћи
Стратегије задржавања запослених 101: Образовање на радном месту
Стратегије задржавања запослених 101: Образовање на радном месту
Финансирање покретања за осниваче: Ваша пратећа контролна листа
Финансирање покретања за осниваче: Ваша пратећа контролна листа
Дизајн за интерактивно окружење и паметне просторе
Дизајн за интерактивно окружење и паметне просторе
Популар Постс
  • укључити датотеку заглавља Ц++
  • а* ц++
  • све анимације на светској мрежи су флеш анимације
  • принципи дефинисања шаблона дизајна
  • како хаковати онлајн систем плаћања
Категорије
  • Иновација
  • Алати И Упутства
  • Укс Дизајн
  • Рисе Оф Ремоте
  • © 2022 | Сва Права Задржана

    portaldacalheta.pt