原文:auth0.com/blog/how-to…css
Auth0 是一個全球領先的 Identity-as-a-Service (IDaaS) 服務商,爲數以千計的企業客戶提供現代身份認證解決方案。除了經典的 「用戶名密碼認證過程」 外,Auth0 也容許你增長諸如 「社交媒體登陸」 、 「多因子認證」、 「無密碼登陸」 等等特性,全部這些只須要一些點擊就能完成。前端
用 Auth0 保證 React 應用安全是十分簡單方便的。react
要完成本文說明的內容,你須要一個 Auth0 帳號。若是你尚未,如今是個 註冊免費 Auth0 帳戶 (auth0.com/signup) 的好時機。npm
同時,若是你想在一個乾淨的環境中完成本章節內容,你能經過一條命令輕易建立一個 React 應用:安全
npx create-react-app react-auth0
複製代碼
而後,進入建立好的 react-auth0
目錄,就能夠按下面的步驟開發了。bash
要爲你的 React 應用賦予一個 Auth0 帳戶,你須要建立一個 Auth0 Application。因此,根據 manage.auth0.com/#/applicati… 的描述作以下操做:前端框架
在建立應用以後,Auth0 會將你重定向到其 Quick Start tab 頁中。你得點擊到 Settings tab 頁去設置一些白名單 URL 以供 Auth0 在認證過程後調用。這是一項 Auth0 實現的安全性措施,用以免敏感數據泄露(如 ID Tokens)。react-router
因此,當你到達 Settings tab 頁時,尋找到 Allowed Callback URLs 並在其中增長 http://localhost:3000/callback
。在本教程中,這個簡單的 URL 就足夠了。app
好了!從 Auth0 的視角看,你已經開始很好的保證你的 React 應用的安全了。框架
要用 Auth0 保證 React 應用安全,只有三項依賴須要安裝:
要安裝這些依賴,到項目根目錄下面執行以下的命令:
npm install --save auth0-js react-router react-router-dom
複製代碼
注意: 若是你想要可得到的最佳安全性,應該依照 auth0.com/docs/univer… 上的說明進行。該方法包括了重定向用戶到一個託管在 Auth0 網站上的登陸頁面,該頁面經過 你的 Auth0 dashboard (manage.auth0.com/) 能夠方便快捷地定製化。若是你想要更多學習這種最佳實踐,可參閱 auth0.com/docs/guides… 頁面。
安裝好這三個庫以後,你就能夠建立一個服務來處理認證過程了。能夠將該服務叫作 Auth
並用以下代碼將其建立到 src/Auth/
目錄:
// src/Auth/Auth.js
import auth0 from 'auth0-js';
export default class Auth {
constructor() {
this.auth0 = new auth0.WebAuth({
// 必須更新如下三行!
domain: '<AUTH0_DOMAIN>',
audience: 'https://<AUTH0_DOMAIN>/userinfo',
clientID: '<AUTH0_CLIENT_ID>',
redirectUri: 'http://localhost:3000/callback',
responseType: 'token id_token',
scope: 'openid profile'
});
this.getProfile = this.getProfile.bind(this);
this.handleAuthentication = this.handleAuthentication.bind(this);
this.isAuthenticated = this.isAuthenticated.bind(this);
this.login = this.login.bind(this);
this.logout = this.logout.bind(this);
this.setSession = this.setSession.bind(this);
}
getProfile() {
return this.profile;
}
handleAuthentication() {
return new Promise((resolve, reject) => {
this.auth0.parseHash((err, authResult) => {
if (err) return reject(err);
console.log(authResult);
if (!authResult || !authResult.idToken) {
return reject(err);
}
this.setSession(authResult);
resolve();
});
})
}
isAuthenticated() {
return new Date().getTime() < this.expiresAt;
}
login() {
this.auth0.authorize();
}
logout() {
// 清除 id token 和過時時間
this.idToken = null;
this.expiresAt = null;
}
setSession(authResult) {
this.idToken = authResult.idToken;
this.profile = authResult.idTokenPayload;
// 設置 id token 的過時時間
this.expiresAt = authResult.expiresIn * 1000 + new Date().getTime();
}
}
複製代碼
你剛剛建立的這個 Auth
服務包含了用於處理登入、登出不一樣步驟的各類函數。下面的列表概述了這些函數:
getProfile
: 返回已登陸用戶的 profilehandleAuthentication
: 查找 URL hash 中的認證過程結果。而後,該函數用 auth0-js
中的 parseHash
方法處理結果isAuthenticated
: 檢查用戶 ID token 是否過時login
: 初始化登陸過程,將用戶重定向到登陸頁面logout
: 清除用戶的 tokens 和過時時間setSession
: 設置用戶的 ID token、profile 及過時時間除了這些函數,該類還包含了一個名爲 auth0
的屬性,用來從你的 Auth0 應用中提取初始化值。同時記住你 必須 替換掉其中的 <AUTH0_DOMAIN>
和 <AUTH0_CLIENT_ID>
佔位符是重要的。
注意: 對於
<AUTH0_DOMAIN>
佔位符,你得將它替換成相似your-subdomain.auth0.com
的形式,其中your-subdomain
是你在建立 Auth0 帳戶(或你的 Auth0 租戶名, auth0.com/docs/gettin…)時選擇的子域名。而對於<AUTH0_CLIENT_ID>
,須要將其替換爲從你以前建立的 Auth0 應用中 Client ID 域中拷貝的隨機字符串。
因爲使用了 Auth0 登陸頁面,用戶會被帶離你的應用。不過,在其認證事後,又會被自動帶回到你以前設置過的回調 URL 上 (也就是 http://localhost:3000/callback
)。這意味着你須要建立一個組件來負責這個路由。
因此,建立 src/Callback
目錄並在其中建立一個叫作 Callback.js
的文件,插入以下的代碼:
// src/Callback/Callback.js
import React from 'react';
import { withRouter } from 'react-router';
function Callback(props) {
props.auth.handleAuthentication().then(() => {
props.history.push('/');
});
return (
<div> Loading user profile. </div>
);
}
export default withRouter(Callback);
複製代碼
這個組件,正如你所見,負責觸發 handleAuthentication
過程,並在該過程結束時將用戶帶入主頁。而當該組件處理認證結果的過程當中,只是簡單的顯示了 「loading the user profile」 。
當 Auth
和 Callback
組件都建立完畢,就能夠重構 App
組件以整合全部事情了:
// src/App.js
import React from 'react';
import {withRouter} from 'react-router';
import {Route} from 'react-router-dom';
import Callback from './Callback/Callback';
import './App.css';
function HomePage(props) {
const {authenticated} = props;
const logout = () => {
props.auth.logout();
props.history.push('/');
};
if (authenticated) {
const {name} = props.auth.getProfile();
return (
<div> <h1>Howdy! Glad to see you back, {name}.</h1> <button onClick={logout}>Log out</button> </div>
);
}
return (
<div> <h1>I don't know you. Please, log in.</h1> <button onClick={props.auth.login}>Log in</button> </div>
);
}
function App(props) {
const authenticated = props.auth.isAuthenticated();
return (
<div className="App">
<Route exact path='/callback' render={() => (
<Callback auth={props.auth}/>
)}/>
<Route exact path='/' render={() => (
<HomePage
authenticated={authenticated}
auth={props.auth}
history={props.history}
/>)
}/>
</div>
);
}
export default withRouter(App);
複製代碼
在本例中,實際上你在一個文件中定義了兩個組件(就是爲了簡單)。首先定義一個 HomePage
組件展現已登陸用戶名的信息,以及告知未登陸用戶去登陸的信息。同時,文件中的 App
組件負責決定根據路由哪些子組件必須渲染。
要注意你在全部組件中(App
、HomePage
和 Callback
)都用到了 Auth
服務。所以你須要這個服務的一個全局實例,而且將其包含在 App
組件中。
因此,要建立這個全局 Auth
實例並整合到應用中,須要更新 index.js
文件:
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import Auth from './Auth/Auth';
import './index.css';
import App from './App';
const auth = new Auth();
ReactDOM.render(
<BrowserRouter> <App auth={auth} /> </BrowserRouter>, document.getElementById('root') ); 複製代碼
這樣就完成了!你已經用 Auth0 保護了你的 React 應用。若是用 npm start
啓動了應用,你將可以藉助 Auth0 的幫助本身實現認證了,也能看到 React 應用顯示了你的名字(若是你的身份提供者確實提供了一個名字的話)。
若是你想學習更多的話,Auth0 官方文檔中也提供了各類前端框架的整合方法:
查看更多前端好文
請搜索 fewelife 關注公衆號
轉載請註明出處