上一章 Day 29 - React Tree Graph 樹狀結構圖
在這隱私權高漲的年代, 所有個資與重要資訊都必須加密
之前有寫過一篇用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的密碼欄位就有加密了
之前都用非同步取資料, 但有些功能仍然需要同步處理(例如: 新增, 刪除)
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刪掉會直接報錯
新增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;
現在啟動專案, 新增會員看看
可以發現新增完會自動更新列表, 是因為我們用了this.props.history.push
30天教學就到這, 有興趣的朋友們可以做看看刪除功能。
有任何問題都歡迎交流討論。