實戰react技術棧+express先後端博客項目(6)-- 使用session實現免登錄+管理後臺權限驗證

項目地址:https://github.com/Nealyang/R...前端

本想等項目作完再連載一波系列博客,隨着開發的進行,也是的確遇到了很多坑,請教了很多人。遂想,何不一邊記錄踩坑,一邊分享收穫呢。分享固然是好的,
若是能作到集思廣益,那豈不是更美。咱們的口號是:堅定不會爛尾react

本博客爲連載代碼博客同步更新博客,隨着項目日後開發可能會遇到前面寫的不合適的地方會再回頭修改。若有不妥~歡迎兄弟們不嗇賜教。謝謝!git

session

後端部分

上一篇文章中,咱們已經實現了先後端的登陸功能。問題你們可能都已經發現了,當刷新頁面的時候,以前登陸過的如今得從新登陸。顯然,這個並非咱們想一想要的。github

因此這裏咱們採用session的機制來解決這類問題。不了session和coolie能夠參考我這篇博客express

apiServer.jsredux

app.use(cookieParser('express_react_cookie'));
app.use(session({
    secret:'express_react_cookie',
    resave: true,
    saveUninitialized:true,
    cookie: {maxAge: 60 * 1000 * 30}//過時時間
}));

由於是登陸信息,因此這裏咱們採用的是session。首先須要在apiServer.js中引入cookie-parser和express-session中間件。segmentfault

coolieParser裏面設置一個key,必需要和session中一致。而後設置coolie的過時時間。這裏咱們設置爲30min。後端

而後再用戶登陸成功了之後,咱們須要設置sessionapi

router.post('/login', (req, res) => {
    let {username, password} = req.body;
    if (!username) {
        responseClient(res, 400, 2, '用戶名不可爲空');
        return;
    }
    if (!password) {
        responseClient(res, 400, 2, '密碼不可爲空');
        return;
    }
    User.findOne({
        username,
        password: md5(password + MD5_SUFFIX)
    }).then(userInfo => {
        if (userInfo) {
            //登陸成功
            let data = {};
            data.username = userInfo.username;
            data.userType = userInfo.type;
            data.userId = userInfo._id;
            //登陸成功後設置session
            req.session.userInfo = data;

            responseClient(res, 200, 0, '登陸成功', data);
            return;
        }
        responseClient(res, 400, 1, '用戶名密碼錯誤');

    }).catch(err => {
        responseClient(res);
    })
});

其中,
req.session.userInfo = data即爲設置session的userInfo。微信

而後再server端須要另寫一個接口。在用戶打開網站的時候就發起請求,驗證用戶是否已經登陸。

//用戶驗證
router.get('/userInfo',function (req,res) {
    if(req.session.userInfo){
        responseClient(res,200,0,'',req.session.userInfo)
    }else{
        responseClient(res,200,1,'請從新登陸',req.session.userInfo)
    }
});

很簡單,就是將請求中的req.session.userInfo的信息返回過去。這樣,當用戶訪問網站的時候,先發送這個請求,來判斷用戶知否已經登錄過。若是已經登錄過,拿到這個userInfo直接put一個action到reducer中,修改state狀態樹便可。

前端部分

前端部分比較常規。在最外層的container中,直接發送請求便可

class AppIndex extends Component {

    constructor(props) {
        super(props);
        this.openNotification = this.openNotification.bind(this);
        this.shouldComponentUpdate = PureRenderMixiin.shouldComponentUpdate.bind(this);
    }

    openNotification(type, message) {
        let that = this;
        notification[type]({
            message: message,
            onClose: () => {
                that.props.clear_msg();
            }
        });
        that.props.clear_msg();
    };

    render() {
        let {isFetching} = this.props;
        return (
            <Router>
                <div>
                    <Switch>
                        <Route path='/404' component={NotFound}/>
                        <Route path='/admin' component={Admin}/>
                        <Route component={Front}/>
                    </Switch>
                    {isFetching && <Loading/>}
                    {this.props.notification && this.props.notification.content ?
                        (this.props.notification.type === 1 ?
                            this.openNotification('success', this.props.notification.content) :
                            this.openNotification('error', this.props.notification.content)) :
                        null}
                </div>
            </Router>
        )
    }

    componentDidMount() {
        this.props.user_auth();
    }

}

而後對應saga的處理也比較常規,這裏再也不贅述。

權限認證

由於是博客系統,因此所謂的權限就是判斷改登陸用戶是否爲管理員。咱們在設計user表的時候,添加了身份一項。固然,咱能夠隨意用別的字符來標識管理員和普通用戶。

render() {
        const {url} = this.props.match;
        if(this.props.userInfo.userType){
            return (
                <div>
                    {
                        this.props.userInfo.userType === 'admin' ?
                            <div className={style.container}>
                                <div className={style.menuContainer}>
                                    <AdminMenu history={this.props.history}
                                               url={this.props.adminUrl}
                                               changeUrl={this.props.change_location_admin}/>
                                </div>
                                <div className={style.contentContainer}>
                                    <Switch>
                                        <Route exact path={url} component={AdminIndex}/>
                                        <Route path={`${url}/managerUser`} component={AdminManagerUser}/>
                                        <Route path={`${url}/managerTags`} component={AdminManagerTags}/>
                                        <Route path={`${url}/newArticle`} component={AdminNewArticle}/>
                                        <Route path={`${url}/detail`} component={Detail}/>
                                        <Route component={NotFound}/>
                                    </Switch>
                                </div>
                            </div> :
                            <Redirect to='/'/>
                    }
                </div>
            )
        }else{
            return <NotFound/>
        }
    }

在admin.js中,咱們判斷state中是否有userInfo這個選項。


若是userInfo是有值的,那麼說明已經登陸。若是沒有值,則跳轉到NotFound頁面。

爲何先顯示notFound界面,而不是在userInfo爲空的時候直接Redirect?

這裏有個大坑,具體看我segmentFault上的提問:react redux身份驗證,取state的問題

以上即爲admin的權限認證,如上,當admin登陸到管理後天的時候,既能夠到管理界面,當不是admin登陸到管理後臺的時候,會直接Redirect到博客首頁。

總結

如上,咱們就直線了用戶的免登錄以及權限管理的問題。主要就是經過session和狀態樹的判斷。
下一篇,咱們就開始後端部分的開發~

## 項目實現步驟系列博客

## 交流

假若有哪裏說的不是很明白,或者有什麼須要與我交流,歡迎各位提issue。或者加羣聯繫我~

掃碼關注個人我的微信公衆號,直接回復,必有迴應。分享更多原創文章。點擊交流學習加我微信、qq羣。一塊兒學習,一塊兒進步

---

歡迎兄弟們加入:

Node.js技術交流羣:209530601

React技術棧:398240621

前端技術雜談:604953717 (新建)

---

相關文章
相關標籤/搜索