iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 30
1
Modern Web

Spring Boot and React - 前後端 30 天分手日記系列 第 30

Day 30 - MySQL Trigger MD5加密 & 同步Fetch API

  • 分享至 

  • xImage
  •  

上一章 Day 29 - React Tree Graph 樹狀結構圖

在這隱私權高漲的年代, 所有個資與重要資訊都必須加密

之前有寫過一篇用Java做MD5加密的文章

Java MD5 加密

今天來講如何用資料庫加密

MySQL Trigger

Trigger 意即觸發事件, 有分以下幾種:

BEFORE INSERT, AFTER INSERT

BEFORE UPDATE, AFTER UPDATE

BEFORE DELETE, AFTER DELETE

我們希望能在新增會員之前, 幫密碼做MD5加密

所以選擇 BEFORE INSERT

CREATE TRIGGER encrypt_pwd BEFORE INSERT ON members FOR EACH ROW SET new.password = md5(new.password);

md5是MySQL裡面自帶的Function

許多DB都有預設MD5 Function可以用, 直接呼叫即可。

現在我們Member的密碼欄位就有加密了

https://ithelp.ithome.com.tw/upload/images/20191016/20119510Iku7ThqPWb.png

之前都用非同步取資料, 但有些功能仍然需要同步處理(例如: 新增, 刪除)

Fetch API也能做到同步, 這裡就用新增會員來示範。

新增AddMember.js

import React, { Component } from 'react';
import { Link, withRouter } from 'react-router-dom';
import {
    Button,
    Container,
    Form,
    FormGroup,
    Input,
    Label
} from 'reactstrap';
import MyNavbar from './MyNavbar';

class AddMember extends Component {
    emptyMember = {
        email: '',
        password: '',
        firstName: '',
        lastName: '',
    };

    constructor(props) {
        super(props);
        this.state = { member: this.emptyMember };
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleChange(event) {
        const target = event.target;
        const value = target.value;
        const name = target.name;
        let member = { ...this.state.member };
        member[name] = value;
        this.setState({ member });
    }

    async handleSubmit(event) {
        event.preventDefault();
        const { member } = this.state;

        await fetch("/api/member", {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(member)
        }).then(response => {
            if(response.status === 201){
                alert("Success");
            }else{
                alert("Failure");
            }
        });
        this.props.history.push('/members');

    }

    render() {
        const { member } = this.state;

        return (
            <div>
                <MyNavbar />
                <Container>
                    <h2>新增會員</h2>
                    <Form onSubmit={this.handleSubmit}>
                        <FormGroup>
                            <Label for="email">Email</Label>
                            <Input type="email" name="email" value={member.email} onChange={this.handleChange}/>
                        </FormGroup>
                        <FormGroup>
                            <Label for="password">Password</Label>
                            <Input type="password" name="password" value={member.password} onChange={this.handleChange}/>
                        </FormGroup>
                        <div className="row">
                            <FormGroup className="col-md-6">
                                <Label for="firstName">firstName</Label>
                                <Input type="text" name="firstName" value={member.firstName} onChange={this.handleChange}/>
                            </FormGroup>
                            <FormGroup className="col-md-6">
                                <Label for="lastName">lastName</Label>
                                <Input type="text" name="lastName" value={member.lastName} onChange={this.handleChange} />
                            </FormGroup>
                        </div>
                        <FormGroup>
                            <Button color="primary" type="submit">Submit</Button>{' '}
                            <Button color="secondary" tag={Link} to="/members">Cancel</Button>
                        </FormGroup>
                    </Form>
                </Container>
            </div>
        )
    }
}

export default withRouter(AddMember);

使用上很簡單, 只要在fetch的前面加上await 就變成同步了

可以看到我們fetch的前綴是await, 但handleSubmit的前綴卻是async

因為await必須要在async裡面才能使用, 如果把外層的async刪掉會直接報錯

https://ithelp.ithome.com.tw/upload/images/20191016/20119510UdQYlqWxDp.png

新增AddMember按鈕
Member.js

import React, { Component } from 'react';
import { Button, ButtonGroup, Container, Table } from 'reactstrap';
import 'bootstrap/dist/css/bootstrap.css';
import { Link } from 'react-router-dom';
import MyNavbar from './MyNavbar';

class Member extends Component {

    constructor(props) {
        super(props);
        this.state = { members: [] };
    }

    componentDidMount() {
        fetch('api/members').then(response => response.json())
            .then(data => this.setState({ members: data }));
    }

    render() {
        const { members } = this.state;

        const memberList = members.map(member => {
            return <tr key={member.mid}>
                <td>{member.email}</td>
                <td>{member.password}</td>
                <td>{member.firstName}</td>
                <td>{member.lastName}</td>
            </tr>
        });

        return (
            <div>
                <MyNavbar />
                <Container fluid>
                    <div className="float-right">
                        <Button color="success" tag={Link} to="/member/new">Add Member</Button>
                    </div>
                    <h3>Member</h3>
                    <Table className="mt-4">
                        <thead>
                            <tr>
                                <th>Email</th>
                                <th>Password</th>
                                <th>FirstName</th>
                                <th>LastName</th>
                            </tr>
                        </thead>
                        <tbody>
                            {memberList}
                        </tbody>
                    </Table>
                </Container>
            </div>
        );
    }

}
export default Member;

現在啟動專案, 新增會員看看
https://ithelp.ithome.com.tw/upload/images/20191016/20119510M3bQXx6BXO.png

可以發現新增完會自動更新列表, 是因為我們用了this.props.history.push
https://ithelp.ithome.com.tw/upload/images/20191016/20119510AcuDcNdY20.png

30天教學就到這, 有興趣的朋友們可以做看看刪除功能。

有任何問題都歡迎交流討論。


上一篇
Day 29 - React Tree Graph 樹狀結構圖
系列文
Spring Boot and React - 前後端 30 天分手日記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
阿展展展
iT邦好手 1 級 ‧ 2020-01-28 06:23:09

恭喜完賽! /images/emoticon/emoticon42.gif
Spring Boot 是一個好長壽的東西啊 !!

我要留言

立即登入留言