Front-End приложение с Spring Security OAuth - поток кода авторизации
1. обзор
В этом руководстве мы продолжим нашSpring Security OAuth series, создав простой интерфейс для потока кода авторизации.
Имейте в виду, что в центре внимания находится клиентская сторона; ознакомьтесь с описаниемSpring REST API + OAuth2 + AngularJS - чтобы просмотреть подробную конфигурацию как для серверов авторизации, так и для серверов ресурсов.
2. Сервер авторизации
Прежде чем мы перейдем к нашему интерфейсу, нам нужно добавить данные нашего клиента в конфигурацию нашего сервера авторизации:
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("fooClientId")
.secret(passwordEncoder().encode("secret"))
.authorizedGrantTypes("authorization_code")
.scopes("foo", "read", "write")
.redirectUris("http://localhost:8089/")
...
Обратите внимание, что теперь у нас включен тип предоставления кода авторизации со следующими простыми подробностями:
-
наш идентификатор клиентаfooClientId
-
наши области:foo,read andwrite
-
URI перенаправления -http://localhost:8089/ (мы собираемся использовать порт 8089 для нашего внешнего приложения)
3. Передний конец
Теперь приступим к созданию нашего простого интерфейсного приложения.
Поскольку мы собираемся использовать Angular 6 для нашего приложения здесь, нам нужно использовать плагинfrontend-maven-plugin в нашем приложении Spring Boot:
com.github.eirslett
frontend-maven-plugin
1.6
v8.11.3
6.1.0
src/main/resources
install node and npm
install-node-and-npm
npm install
npm
npm run build
npm
run build
Обратите внимание, что, естественно, нам сначала нужно установитьNode.js на наш ящик; мы будем использовать Angular CLI для создания базы для нашего приложения:
нг новый код авторизации
4. Угловой модуль
Теперь давайте подробно обсудим наш модуль Angular.
Вот наш простойAppModule:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { HomeComponent } from './home.component';
import { FooComponent } from './foo.component';
@NgModule({
declarations: [
AppComponent,
HomeComponent,
FooComponent
],
imports: [
BrowserModule,
HttpClientModule,
RouterModule.forRoot([
{ path: '', component: HomeComponent, pathMatch: 'full' }], {onSameUrlNavigation: 'reload'})
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Наш модуль состоит из трех компонентов и одной службы, мы обсудим их в следующих разделах.
4.1. Компонент приложения
Начнем с нашегоAppComponent, который является корневым компонентом:
import {Component} from '@angular/core';
@Component({
selector: 'app-root',
template: `
`
})
export class AppComponent {}
4.2. Домашний компонент
Далее идет наш основной компонентHomeComponent:
import {Component} from '@angular/core';
import {AppService} from './app.service'
@Component({
selector: 'home-header',
providers: [AppService],
template: `
`
})
export class HomeComponent {
public isLoggedIn = false;
constructor(
private _service:AppService){}
ngOnInit(){
this.isLoggedIn = this._service.checkCredentials();
let i = window.location.href.indexOf('code');
if(!this.isLoggedIn && i != -1){
this._service.retrieveToken(window.location.href.substring(i + 5));
}
}
login() {
window.location.href = 'http://localhost:8081/spring-security-oauth-server/oauth/authorize?response_type=code&client_id=' + this._service.clientId + '&redirect_uri='+ this._service.redirectUri;
}
logout() {
this._service.logout();
}
}
Обратите внимание, что:
-
Если пользователь не вошел в систему, появится только кнопка входа в систему
-
Кнопка входа перенаправляет пользователя на URL авторизации
-
Когда пользователь перенаправляется обратно с кодом авторизации, мы получаем токен доступа, используя этот код
4.3. Компонент Foo
Наш третий и последний компонент -FooComponent; это отображает ресурсыFoo, полученные с сервера ресурсов:
import { Component } from '@angular/core';
import {AppService, Foo} from './app.service'
@Component({
selector: 'foo-details',
providers: [AppService],
template: `
Foo Details
{{foo.id}}
{{foo.name}}
`
})
export class FooComponent {
public foo = new Foo(1,'sample foo');
private foosUrl = 'http://localhost:8082/spring-security-oauth-resource/foos/';
constructor(private _service:AppService) {}
getFoo(){
this._service.getResource(this.foosUrl+this.foo.id)
.subscribe(
data => this.foo = data,
error => this.foo.name = 'Error');
}
}
4.4. Служба приложений
Теперь посмотрим наAppService:
import {Injectable} from '@angular/core';
import { Cookie } from 'ng2-cookies';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
export class Foo {
constructor(
public id: number,
public name: string) { }
}
@Injectable()
export class AppService {
public clientId = 'fooClientId';
public redirectUri = 'http://localhost:8089/';
constructor(
private _http: HttpClient){}
retrieveToken(code){
let params = new URLSearchParams();
params.append('grant_type','authorization_code');
params.append('client_id', this.clientId);
params.append('redirect_uri', this.redirectUri);
params.append('code',code);
let headers = new HttpHeaders({'Content-type': 'application/x-www-form-urlencoded; charset=utf-8', 'Authorization': 'Basic '+btoa(this.clientId+":secret")});
this._http.post('http://localhost:8081/spring-security-oauth-server/oauth/token', params.toString(), { headers: headers })
.subscribe(
data => this.saveToken(data),
err => alert('Invalid Credentials')
);
}
saveToken(token){
var expireDate = new Date().getTime() + (1000 * token.expires_in);
Cookie.set("access_token", token.access_token, expireDate);
console.log('Obtained Access token');
window.location.href = 'http://localhost:8089';
}
getResource(resourceUrl) : Observable{
var headers = new HttpHeaders({'Content-type': 'application/x-www-form-urlencoded; charset=utf-8', 'Authorization': 'Bearer '+Cookie.get('access_token')});
return this._http.get(resourceUrl,{ headers: headers })
.catch((error:any) => Observable.throw(error.json().error || 'Server error'));
}
checkCredentials(){
return Cookie.check('access_token');
}
logout() {
Cookie.delete('access_token');
window.location.reload();
}
}
Давайте сделаем здесь краткое изложение нашей реализации:
-
checkCredentials(): чтобы проверить, вошел ли пользователь в систему
-
retrieveToken(): для получения токена доступа с помощью кода авторизации
-
saveToken(): для сохранения токена доступа в cookie
-
getResource(): чтобы получить подробную информацию о Foo, используя его идентификатор
-
logout(): удалить cookie токена доступа
5. Запустите приложение
Чтобы запустить наше приложение и убедиться, что все работает правильно, нам необходимо:
-
Сначала запустите Сервер авторизации на порту 8081
-
Затем запустите сервер ресурсов на порту 8082
-
Наконец, запустите Front End
Сначала нам нужно собрать наше приложение:
mvn clean install
Затем измените каталог на src / main / resources:
cd src/main/resources
Затем запустите наше приложение на порт 8089:
npm start
6. Заключение
Мы узнали, как создать простой клиент переднего плана для потока кода авторизации, используя Spring и Angular 6.
И, как всегда, доступен полный исходный кодover on GitHub.