สวัสดีครับ สำหรับในบทความนี้จะเกียวกับ การใช้งาน Firebase Authentication กันครับ โดยในตัวอย่างจะใช้ React Js ซึ่งในบทความนี้จะต่อเนื้องจากบทความที่แล้วครับ
การใช้งาน Firebase Realtime Database ด้วย ReactJs
จาก เนื้อหาในตอนที่แล้ว เราได้ทำการสร้าง App ง่าย ๆ ให้สามารถ บันทึก และ แก้ไข ข้อมูลกันไปแล้ว แต่ในตอนนี้ เราจะมาเพิ่มหน้าจอ ให้สามารถ Login และ Logout ได้ครับ
โดยวิธีการใช้งาน Firebase Authentication โดยละเอียด ดูได้ที่
https://firebase.google.com/docs/auth/web/password-auth?authuser=0
ก่อนอื่นเรามาแก้ไขไฟล์ firebase.js กันก่อนครับ
โดยเราจะเพิ่ม export const auth = firese.auth(); เพื่อใช้งาน ฟังชั่น authentication ครับ
import * as firebase from 'firebase'; //insert config from firebase const config = { apiKey: "AIzaSyBaYasdfmYbormmmRHpff2WasdfMuYVBDas6ev3G9k", authDomain: "toasdfdo-7ffasdfb6.firebaseapp.com", databaseURL: "https://todo-7asdfffb6.firebaseio.com", projectId: "todo-7ffbasdf6", storageBucket: "todo-7ffasdfb6.appspot.com", messagingSenderId: "2458asdf3sdf9549110" }; firebase.initializeApp(config); //add code firebase.auth export const auth = firebase.auth(); export default firebase;
ต่อมาเรามาแก้ไขไฟล์ App.js กันต่อเลยครับ
ในส่วนของ import firebase เพิ่ม การเรียกใช้งาน function auth ของ firebase
import React, { Component } from 'react'; import firebase,{auth } from './firebase' class App extends Component {
ในส่วนของ state เราจะทำการเพิ่ม state email,password, และ isLogin ใช้สำหรับตรวจสอบว่าได้มีการ Login แล้ว หรือยังโดยค่าเร่ิมต้นคือ false หมายถึงยังไม่ได้ Login
this.state = { items:[], item_id:'', title:'', description:'', email:'',//add email state password:'',//add password state isLogin:false //add isLogin state }
ใน constructor เพิ่มการ bind ใน function login และ logout เพื่อให้สามารถ จัดการ กับ ค่าที่อยู่ภายใน state ได้
this.login = this.login.bind(this) this.logout = this.logout.bind(this)
เพิ่ม function login และ logout
ใน function login จะมีการเรียกใช้งาน signInWithEmailAndPassword โดยมีการส่ง email ,password เพื่อไปตรวจสอบว่า เป็นผู้ใช้จริงหรือไม่ หาก จริง จะมีการ setState ให้ isLogin เป็น true
ในส่วนของ function logout เรียกใช้งาน auth.signOut หากสำเร็จ จะมีการ setState ให้ isLogin เป็น false
login = () =>{ firebase.auth().signInWithEmailAndPassword(this.state.email, this.state.password).then(() => { this.setState({ isLogin : true }); }).catch(function(error) { var errorCode = error.code; var errorMessage = error.message; if (errorCode === 'auth/wrong-password') { alert('Wrong password.'); } else { alert(errorMessage); } console.log(error); }); } logout(){ auth.signOut().then(() => { this.setState({isLogin:false}) }) }
เพิ่ม function loginForm เพื่อแสดงหน้า สำหรับ กรอก Username , Password
loginForm(){ return( <div> <main role="main" className="container" style={{marginTop:80}}> <div className="row"> <div className="col-4"></div> <div className="col-4"> <form> <div class="form-group"> <label for="exampleInputEmail1">Email address</label> <input type="email" class="form-control" name="email" onChange={this.handleChange} value={this.state.email} placeholder="Enter email"/> <small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small> </div> <div class="form-group"> <label for="exampleInputPassword1">Password</label> <input type="password" class="form-control" name="password" onChange={this.handleChange} value={this.state.password} placeholder="Password"/> </div> <a class="btn btn-primary" onClick={() => this.login()}>Log In</a> </form> </div> </div> </main> </div> ) }
เพิ่มการตรวจสอบว่า ได้มีการ Login แล้วหรือยัง โดยหาก isLogin เป็น false ให้เรียกใช้งาน loginForm
render() { if(!this.state.isLogin){ return this.loginForm() } //....
เพิ่มการแสดงปุ่ม Logout เมื่อ isLogin มีค่าเป็น true
return ( <div className="app"> <nav class="navbar navbar-light bg-primary"> <span class="navbar-brand mb-0 h1">Todo List</span> { this.state.isLogin ? <a className="btn btn-danger" onClick={() => this.logout()} >Logout</a> : null } </nav> //..
จากนั้นทดลอง run คำสั่ง npm start จะพบกับหน้าจอ Login
มาถึงตอนนี้เราก็ได้เพิ่ม Code ในส่วนของการ Authentication ด้วย Firebase เรียบร้อยแล้ว แต่ยังไม่สามารถใช้งานได้ เนื่องจากเราต้องไปทำการเปิดใช้งาน Authentication ใน Firebase Control กันก่อนครับ
การเปิดใช้งาน Firebase Authentication
1.ไปที่ https://console.firebase.google.com/u/0/
2.ในตัวอย่างจะเลือก Project todo ซึ่งเป็น Project เดิมจากตอนที่แล้วครับ
จากนั้นเลือกที่ เมนู Authentication จากนั้นเลือก เมนู วิธีการลงชื่อเข้าใช้ ใน Tab ด้านบน ครับ
3.เลือกที่ หัวข้อ อีเมล/รหัสผ่าน จากนั้นให้คลิก เปิดใช้งาน และ บันทึกครับ
4. ไปที่ Tab ผู้ใช้ ด้านบน ทำการเพิ่ม User ที่เราต้องการ โดยการคลิกที่ปุ่ม เพิ่มผู้ใช้ครับ
5.เสร็จสิ้นข้อตอนการตั้งค่าที่ Firebase ครับ
ทำการทดสอบที่หน้าเว็บ React Js ที่เราสร้างขึ้น หาก Login สำเร็จจะแสดงหน้า ของ todo List
เมื่อกด Logout ก็จะเปลี่ยนหน้า Login ขึ้นมาครับ
ตัวอย่างไฟล์ App.js แบบเต็ม ๆ
import React, { Component } from 'react'; import firebase,{auth } from './firebase' class App extends Component { constructor(){ super(); this.state = { items:[], item_id:'', title:'', description:'', email:'',//add email state password:'',//add password state isLogin:false //add isLogin state } this.handleChange = this.handleChange.bind(this) this.handleUpdate = this.handleUpdate.bind(this) this.handleSubmit = this.handleSubmit.bind(this) this.login = this.login.bind(this) this.logout = this.logout.bind(this) } componentDidMount(){ auth.onAuthStateChanged((user) => { if(user){ this.setState({user}) } }) const itemsRef = firebase.database().ref('items'); itemsRef.on('value',(snapshot) => { let items = snapshot.val(); let newState = []; for(let item in items){ newState.push({ item_id:item, title:items[item].title, description:items[item].description }) } this.setState({ items:newState }) }) } handleChange(e){ this.setState({ [e.target.name]: e.target.value }) } handleSubmit(e){ e.preventDefault(); if(this.state.item_id !== ''){ return this.updateItem(); } const itemsRef = firebase.database().ref('items') const item = { title : this.state.title, description : this.state.description } itemsRef.push(item) this.setState({ item_id:'', title:'', description:'' }) } handleUpdate = (item_id = null , title = null , description = null) => { this.setState({item_id,title,description}) } updateItem(){ var obj = { title:this.state.title,description:this.state.description } const itemsRef = firebase.database().ref('/items') itemsRef.child(this.state.item_id).update(obj); this.setState({ item_id:'', title:'', description:'' }) } removeItem(itemId){ const itemsRef = firebase.database().ref('/items'); itemsRef.child(itemId).remove(); } login = () =>{ firebase.auth().signInWithEmailAndPassword(this.state.email, this.state.password).then(() => { this.setState({ isLogin : true }); }).catch(function(error) { var errorCode = error.code; var errorMessage = error.message; if (errorCode === 'auth/wrong-password') { alert('Wrong password.'); } else { alert(errorMessage); } console.log(error); }); } logout(){ auth.signOut().then(() => { this.setState({isLogin:false}) }) } loginForm(){ return( <div> <main role="main" className="container" style={{marginTop:80}}> <div className="row"> <div className="col-4"></div> <div className="col-4"> <form> <div class="form-group"> <label for="exampleInputEmail1">Email address</label> <input type="email" class="form-control" name="email" onChange={this.handleChange} value={this.state.email} placeholder="Enter email"/> <small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small> </div> <div class="form-group"> <label for="exampleInputPassword1">Password</label> <input type="password" class="form-control" name="password" onChange={this.handleChange} value={this.state.password} placeholder="Password"/> </div> <button class="btn btn-primary" onClick={() => this.login()}>Log In</button> </form> </div> </div> </main> </div> ) } render() { if(!this.state.isLogin){ return this.loginForm() } return ( <div className="app"> <nav class="navbar navbar-light bg-primary"> <span class="navbar-brand mb-0 h1">Todo List</span> { this.state.isLogin ? <button className="btn btn-danger" onClick={() => this.logout()} >Logout</button> : null } </nav> <div className="container" style={{marginTop:70}}> <form onSubmit={this.handleSubmit}> <div className="row"> <div className="col-8"> <div className="form-row"> <div className="col-4"> <input type="text" name="title" className="form-control" placeholder="Title" onChange={this.handleChange} value={this.state.title}/> </div> <div className="col-6"> <input type="text" name="description" className="form-control" placeholder="Description" onChange={this.handleChange} value={this.state.description}/> </div> <div className="col"> <button class="btn btn-primary" > Save</button> </div> </div> </div> </div> </form> <hr/> <table className="table table-sm table-bordered"> <tr className="thead-dark"> <th width="20%">Title</th> <th width="70%">Description</th> <th width="5%">Edit</th> <th width="5%">Delete</th> </tr> { this.state.items.map((item) => { return ( <tr> <td>{item.title}</td> <td>{item.description}</td> <td><button className="btn btn-warning btn-sm" onClick={() => this.handleUpdate(item.item_id,item.title,item.description)}>Edit</button></td> <td><button className="btn btn-danger btn-sm" onClick={() => this.removeItem(item.item_id)}>Delete</button></td> </tr> ) }) } </table> </div> </div> ); } } export default App;