1. Обзор
В этом уроке мы продолжим нашу серию Spring Security OAuth, создав простой интерфейс для потока кода авторизации.
Имейте в виду, что основное внимание здесь уделяется стороне клиента; взгляните на запись 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/") ...
Обратите внимание, что теперь у нас включен тип предоставления кода авторизации со следующими простыми деталями:
- наш идентификатор клиента – foo ClientID
- наши области видимости: foo , чтение и запись
- URL-адрес перенаправления: http://localhost:8089/ (мы собираемся использовать порт 8089 для нашего интерфейсного приложения)
3. Передний Конец
Теперь давайте начнем создавать наше простое интерфейсное приложение.
Поскольку мы собираемся использовать Angular 6 для нашего приложения здесь, нам нужно использовать интерфейс-maven-плагин плагин в нашем приложении 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 для создания базы для нашего приложения:
ng новый код авторизации
4. Угловой Модуль
Теперь давайте подробно обсудим наш угловой модуль.
Вот наш простой Модуль приложения :
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. Компонент приложения
Давайте начнем с нашего Компонента приложения , который является корневым компонентом:
import {Component} from '@angular/core'; @Component({ selector: 'app-root', template: `` }) export class AppComponent {}
4.2. Домашний компонент
Далее идет наш основной компонент, Домашний компонент :
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
Наш третий и последний компонент-это FooКомпонент ; здесь отображаются Foo ресурсы, полученные с сервера ресурсов:
import { Component } from '@angular/core'; import {AppService, Foo} from './app.service' @Component({ selector: 'foo-details', providers: [AppService], template: `` }) 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'); } }Foo Details
{{foo.id}}{{foo.name}}
4.4. Сервис приложений
Теперь давайте взглянем на Службу приложений :
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(); } }
Давайте кратко рассмотрим нашу реализацию здесь:
- проверьте учетные данные() : чтобы проверить, вошел ли пользователь в систему
- retrieveToken() : для получения маркера доступа с помощью кода авторизации
- сохранить токен() : для сохранения токена доступа в файле cookie
- getResource() : для получения сведений о Foo, используя его идентификатор
- выход из системы() : для удаления файла cookie маркера доступа
5. Запустите приложение
Чтобы запустить наше приложение и убедиться, что все работает правильно, нам нужно:
- Сначала запустите Сервер авторизации на порту 8081
- Затем запустите сервер ресурсов на порту 8082
- Наконец, запустите передний конец
Сначала нам нужно будет создать наше приложение:
mvn clean install
Затем измените каталог на src/main/ресурсы:
cd src/main/resources
Затем запустите наше приложение на порту 8089:
npm start
6. Заключение
Мы узнали, как создать простой интерфейсный клиент для потока кода авторизации с помощью Spring и Angular 6.
И, как всегда, полный исходный код доступен на GitHub .