原文: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 关注公众号
转载请注明出处