Last active
April 9, 2019 07:01
-
-
Save ZhenDeng/339bbe46490f4093ee73bfa7dc16876a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1. Go to appsettings.json file and add the secret key for the JWT encryption. | |
"AppSettings": { | |
"Secret": "HHPM0JEOMLGYXYU5YS32" | |
}, | |
2. Create a class as “AppSettings.cs” to access the AppSetting values trough a class. | |
namespace NetCoreWebAPI.Helpers | |
{ | |
public class AppSettings | |
{ | |
public string Secret { get; set; } | |
} | |
} | |
3. Add the following code to Startup.cs class to configure the request pipeline to handle all requests. | |
No need to add additional assemblies. All the relevant assemblies will be at .Net core project by default. | |
namespace NetCoreWebAPI | |
{ | |
public class Startup | |
{ | |
public Startup(IConfiguration configuration) | |
{ | |
Configuration = configuration; | |
} | |
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) | |
{ | |
services.AddMvc(); | |
// JWT related code | |
services.AddCors(); | |
// Configure asettings.jason values to an objects | |
var appSettingsSection = Configuration.GetSection("AppSettings"); | |
services.Configure<AppSettings>(appSettingsSection); | |
// Configure JWT authentication | |
var appSettings = appSettingsSection.Get<AppSettings>(); | |
var key = Encoding.ASCII.GetBytes(appSettings.Secret); | |
services.AddAuthentication(x => | |
{ | |
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; | |
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; | |
}) | |
.AddJwtBearer(x => | |
{ | |
x.RequireHttpsMetadata = false; | |
x.SaveToken = true; | |
x.TokenValidationParameters = new TokenValidationParameters | |
{ | |
ValidateIssuerSigningKey = true, | |
IssuerSigningKey = new SymmetricSecurityKey(key), | |
ValidateIssuer = false, | |
ValidateAudience = false | |
}; | |
}); | |
} | |
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. | |
public void Configure(IApplicationBuilder app, IHostingEnvironment env) | |
{ | |
if (env.IsDevelopment()) | |
{ | |
app.UseDeveloperExceptionPage(); | |
} | |
// JWT related code | |
app.UseCors(x => x | |
.AllowAnyOrigin() | |
.AllowAnyMethod() | |
.AllowAnyHeader() | |
.AllowCredentials()); | |
app.UseAuthentication(); | |
app.UseMvc(); | |
} | |
} | |
} | |
4. Create a Model class as UserModel | |
namespace NetCoreWebAPI.Models | |
{ | |
public class UserModel | |
{ | |
public string Username { get; set; } | |
public string Password { get; set; } | |
} | |
} | |
5. Add new API Controller as “UserController” | |
namespace NetCoreWebAPI.Controllers | |
{ | |
[Produces("application/json")] | |
[Route("api/User")] | |
public class UserController : Controller | |
{ | |
private readonly AppSettings _appSettings; | |
public UserController(IOptions<AppSettings> appSettings) | |
{ | |
_appSettings = appSettings.Value; | |
} | |
[AllowAnonymous] | |
[HttpPost("authenticate")] | |
public IActionResult Authenticate([FromBody]UserModel userModel) | |
{ | |
if(ModelState.IsValid) | |
{ | |
if(userModel.Username != "admin" || userModel.Password != "123") | |
{ | |
return Unauthorized(); | |
} | |
var tokenHandler = new JwtSecurityTokenHandler(); | |
var key = Encoding.ASCII.GetBytes(_appSettings.Secret); | |
var tokenDescriptor = new SecurityTokenDescriptor | |
{ | |
Subject = new ClaimsIdentity(new Claim[] | |
{ | |
new Claim(ClaimTypes.Name, userModel.Username) | |
}), | |
Expires = DateTime.UtcNow.AddMinutes(20), | |
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) | |
}; | |
var token = tokenHandler.CreateToken(tokenDescriptor); | |
var tokenString = tokenHandler.WriteToken(token); | |
// return basic user info and token to store client side | |
return Ok(new | |
{ | |
Username = userModel.Username, | |
Token = tokenString | |
}); | |
} | |
else | |
{ | |
return Unauthorized(); | |
} | |
} | |
} | |
} | |
6. add a test controller | |
[Route("api/[Controller]")] | |
[Authorize] | |
public class CompanyInfoController: Controller | |
{ | |
[HttpGet] | |
public IActionResult Get() | |
{ | |
return Ok("test"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1. in app.route.ts | |
const appRoutes: Routes = [ | |
{ path: 'home', component: HomeComponent, canActivate: [AuthGuard] }, | |
{ path: 'account', component: AccountDetailsComponent, canActivate: [AuthGuard] }, | |
{ | |
path: 'login', component: LoginComponent | |
}, | |
{ | |
path: '', | |
redirectTo: '/home', | |
pathMatch: 'full' | |
} | |
]; | |
export const RoutingModule: ModuleWithProviders = RouterModule.forRoot(appRoutes); | |
2. in app.module.ts | |
@NgModule({ | |
declarations: [ | |
AppComponent, | |
HomeComponent, | |
LoginComponent | |
], | |
imports: [ | |
BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }), | |
HttpClientModule, | |
FormsModule, | |
RoutingModule, | |
BrowserAnimationsModule, | |
MatFormFieldModule, | |
ReactiveFormsModule, | |
MatInputModule | |
], | |
providers: [ | |
UserService, | |
AuthGuard, | |
{ | |
provide: HTTP_INTERCEPTORS, | |
useClass: AuthInterceptor, | |
multi: true | |
}], | |
bootstrap: [AppComponent] | |
}) | |
export class AppModule { } | |
3. in user.service.ts | |
@Injectable() | |
export class UserService { | |
selectedUser: User; | |
base_url: string = "api/User"; | |
constructor(private http: HttpClient) { } | |
userAuthentication(user: any): Observable<UserResponse> { | |
console.info(user); | |
return this.http.post(this.base_url + "/authenticate", user, {headers: new HttpHeaders({'Content-Type':'application/json', 'No-Auth': 'True'})}) | |
.pipe(catchError(this.handleError)); | |
} | |
private handleError(error: HttpErrorResponse) { | |
console.error('server error:', error); | |
if (error.error instanceof ErrorEvent) { | |
let errMessage = ''; | |
try { | |
errMessage = error.error.message; | |
} catch (err) { | |
errMessage = error.statusText; | |
} | |
return Observable.throw(errMessage); | |
} | |
return Observable.throw(error.error || 'ASP.NET Core server error'); | |
} | |
} | |
4. in auth.guard.ts | |
@Injectable() | |
export class AuthGuard implements CanActivate { | |
constructor(private router: Router){} | |
canActivate( | |
next: ActivatedRouteSnapshot, | |
state: RouterStateSnapshot): boolean { | |
if(localStorage.getItem('userToken') != null) { | |
return true; | |
} | |
else{ | |
this.router.navigate(['/login']); | |
return false; | |
} | |
} | |
} | |
5. in auth.interceptor.ts | |
@Injectable() | |
export class AuthInterceptor implements HttpInterceptor { | |
constructor(private router: Router) {} | |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { | |
if(request.headers.get('No-Auth') == "True"){ | |
return next.handle(request.clone()); | |
} | |
if(localStorage.getItem('userToken') != null) { | |
return next.handle( | |
request.clone( | |
{ headers: request.headers.set("Authorization", "Bearer " + localStorage.getItem('userToken'))} | |
) | |
); | |
} | |
else{ | |
this.router.navigateByUrl('/login'); | |
} | |
} | |
} | |
6. in login component | |
<div class="login-box" [formGroup]="userFormGroup"> | |
<p>MEMBER LOGIN</p> | |
<mat-form-field [floatLabel]="'always'" class="col-md-12"> | |
<input matInput formControlName="account" placeholder="USERNAME"> | |
</mat-form-field> | |
<mat-form-field [floatLabel]="'always'" class="col-md-12"> | |
<input matInput formControlName="password" placeholder="PASSWORD"> | |
</mat-form-field> | |
<button class="btn btn-long" (click)="onSubmit()">LOGIN IN</button> | |
<button class="btn btn-long">FORGETTEN PASSWORD?</button> | |
</div> | |
export class LoginComponent implements OnInit { | |
userFormGroup: FormGroup; | |
constructor( | |
private userService: UserService, | |
private router: Router, | |
private formBuilder: FormBuilder) { | |
this.userFormGroup = this.formBuilder.group({ | |
account: new FormControl("", Validators.compose([Validators.required])), | |
password: new FormControl("", Validators.compose([Validators.required])) | |
}); | |
} | |
ngOnInit() { | |
} | |
onSubmit() { | |
this.userService.userAuthentication(this.userFormGroup.value).subscribe((data: UserResponse) => { | |
console.info(data); | |
localStorage.setItem('userToken', data.token); | |
this.router.navigate(['/home']) | |
}, | |
(error: any) => { | |
console.info(error); | |
}); | |
} | |
} | |
7. can get data from test controller with [Authorize] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment