读书笔记《hands-on-full-stack-development-with-spring-boot-2-0-and-react》保护您的应用程序
本章说明当我们在后端使用 JWT 身份验证时,如何对我们的前端实施身份验证。一开始,我们打开后端的安全性以启用 JWT 身份验证。然后,我们为登录功能创建一个组件。最后,我们修改我们的 CRUD 功能以将请求的 Authorization
标头中的令牌发送到后端。
在本章中,我们将看到以下内容:
- How to create a login functionality on our frontend
- How to implement conditional rendering after authentication
- What is needed for CRUD functionalities when the JWT authentication is enabled
- How to show messages when authentication fails
我们在 第 4 章中创建的 Spring Boot 应用程序, 安全和测试您的后端,(GitHub: https://github.com/PacktPublishing/Hands-On-Full-Stack-Development-with-Spring-Boot-2.0-和-React/tree/master/Chapter%204)。
我们在上一章中使用的 React 应用程序 (GitHub: https://github.com/PacktPublishing/Hands-On-Full-Stack-Development-with-Spring-Boot-2.0-和-React/tree/master/Chapter%2011)。
我们使用不安全的后端为我们的 前端实现了CRUD 功能。现在,是时候为我们的后端再次打开安全性并返回到我们在 第 4 章中创建的版本,< span class="emphasis">保护和测试您的后端:
- Open your backend project with the Eclipse IDE and open the
SecurityConfig.java
file in the editor view. We commented the security out and allowed everyone access to all endpoints. Now, we can remove that line and also remove the comments from the original version. Now yourSecurityConfig.java
file'sconfigure
method should look like the following:
让我们测试一下当后端现在再次受到保护时会发生什么。
- Run the backend by pressing the
Run
button in Eclipse and check from theConsole
view that the application started correctly. Run the frontend by typing thenpm start
command into your terminal and the browser should be opened to the addresslocalhost:3000
.
- You should now see the list page and the table are empty. If you open the developer tools, you will notice that the request ends in the
403 Forbidden
HTTP error. This is actually what we wanted because we haven't done the authentication yet to our frontend:
身份验证是使用 JWT 实现到后端的。在第 4 章中, 保护和测试您的后端 span>,我们创建了 JWT 身份验证, /login
endpoint 允许所有人无需身份验证。在前端的登录page 我们要先调用/login
获取令牌的端点。之后,令牌将包含在我们发送到后端的所有请求中,如 Chapter 4 中所示, < span class="emphasis">保护和测试您的后端。
让我们首先创建一个登录组件,该组件要求用户提供凭据以从后端获取令牌:
- Create a new file, called
Login.js
, in thecomponents
folder. Now, your file structure of the frontend should be the following:
- Open the file in the VS Code editor view and add the following base code to the login component. We are also importing
SERVER_URL
because it is needed in a login request:
- In the user interface, we are going to use the Material-UI component library, as we did with the rest of the user interface. We need text field components for the credentials and a button to call a login function. Add imports for the components to the
login.js
file:
- Add imported components to a user interface by adding these to the
render()
method. We need twoTextField
components, one for the username and one for the password. OneRaisedButton
component is needed to call thelogin
function that we are going to implement later in this section:
- Implement the change handler for the
TextField
components to save typed values to the states:
- As shown in Chapter 4, Securing and Testing Your Backend, the login is done by calling the
/login
endpoint using thePOST
method and sending the user object inside the body. If authentication succeeds, we get a token in a responseAuthorization
header. We will then save the token to session storage and set theisAuthenticated
state value totrue
. The session storage is similar to local storage but it is cleared when a page session ends. When theisAuthenticated
state value is changed, the user interface is re-rendered:
- We can implement conditional rendering, which renders the
Login
component if theisAuthenticated
state isfalse
or theCarlist
component ifisAuthenticated
state istrue
. We first have to import theCarlist
component to theLogin
component:
然后对 render()
方法进行如下更改:
- To show the login form, we have to render the
Login
component instead of theCarlist
component in theApp.js
file:
现在,当您的前端和 backend 正在运行时,您的前端应该如下所示:
如果您使用 user/user
或 admin/admin
凭据登录,您应该会看到汽车列表页面。如果您打开开发者工具,您可以看到令牌现在已保存到会话存储中:
汽车列表仍然是空的,但这是正确的,因为我们还没有将令牌包含在请求中。这是 JWT 身份验证所必需的,我们将在下一阶段实施:
- Open the
Carlist.js
file in the VS Code editor view. To fetch the cars, we first have to read the token from the session storage and then add theAuthorization
header with the token value to the request. You can see the source code of the fetch function here:
- If you log in to your frontend, you should see the car list populated with cars from the database:
- Check the request content from the developer tools; you can see that it contains the
Authorization
header with the token value:
所有其他 CRUD 功能都需要 same 修改才能正常工作。修改后删除函数的源代码如下:
修改后的add函数源代码如下:
最后,更新函数的源代码如下所示:
现在,在您登录到应用程序后,所有 CRUD 功能都可以正常工作。
在最后阶段,我们将实现一个 error 消息,如果身份验证失败,该消息会显示给最终用户。我们正在使用 Material-UI SnackBar
组件来显示消息:
- Add the following import to the
Login.js
file:
- Open the state for Snackbar, as we did in Chapter 10, Adding CRUD Functionalities:
我们还需要 Snackbar
打开状态的状态处理程序以在我们在 Snackbar
="literal">SnackbarautoHideDuration
道具:
- Add
Snackbar
to therender()
method:
- Set the
open
state value totrue
if the authentication fails:
如果您现在使用错误的凭据登录,您可以看到 toast 消息:
注销功能更多 易于实现。您基本上只需从会话存储中删除令牌并将 isAuthenticated
状态值更改为 false
,如下面的源代码所示代码:
然后使用条件渲染,可以渲染 Login
组件,而不是 Carlist
。
如果您想使用 React Router 实现菜单,则可以实现所谓的安全路由,该路由只有在用户通过身份验证时才能访问。以下源代码显示了安全路由,如果用户通过身份验证,则显示路由组件,否则重定向到登录页面:
这是使用我们在上一个示例中定义的 SecuredRoute
的 Switch
路由器的示例。 Login
和 Contact
组件无需身份验证即可访问,但 Shop
需要认证:
Packt 还有其他学习 React 的好资源: