Haytham журнал развития персональный блог - Колба + Вью вошли управление на основе маркеров и маршрутизации

указательный столб

В соответствии с тем, что ключевыми словами, этот блог возможно поможет

  • Не использовать фабричные функции КОЛБУ приложения
  • Применение Настой не использует план
  • Колба конфигурации поперечного домена
  • Токен управление государством на основе логина
  • Колба + Вью
  • Вьет перехват маршрутизации
  • Вардар крюк

Применяемая сцена

Это личный блог, чтобы построить блог записи, является простым и колба Вью на «книги», окончательный код будет включать в себя веб-разработчики часто используемые функции. (Неполный, для использования относительно высокой частоты, за исключением)

окружающая среда

  • Система: не зависит от
  • Колба (python3)
  • Вью (Node.js)

ссылка

«Реальное развитие Колба Веб - разработка на Python на основе веб - приложения»
Vue.js

фон

Личные решения блог так много, то почему я должен строить себя это?
На самом деле, цель состоит в том, чтобы не создавать личный блог написанный непосредственно с помощью WordPress блог ... или личный блог , но я хотел , чтобы практиковать эту технологию они учатся, принимая во внимание будущее может присоединиться к балансировки нагрузки, методы кластеризации, что приводит к существенным изменениям в архитектуре или попробовать голосовое управление и другие новые игры играют, код построчно из о целесообразности операции обязательно лучше.

Код функции

Функция Блог не является совершенным, только для достижения следующих основных функций
Спереди: Регистрация Вход, создание блога (уценки редактор) Главная тянуть все статьи, создать блог , нужно войти в состояние.
Сзади: услуга требует больше функции просмотра, конфигураций междоменных, маркер управления и аутентификации, управления базами данных.

Для целей записей обмена добьетесь вошли в управляемом коде можно резюмировать следующим образом

Реализация идей

Для осуществления государственного управления на основе маркера входа в систему, идея заключается в следующем

  1. Пароль учетной записи переднего конца представить фон
  2. Фон проверки, с помощью этого маркера возвращается
  3. Перед тем как на переднем конце каждого запроса маркера, который предусмотрен для запроса заголовка (используется Аксиос крючков)
  4. Предпосылки приобретения защищенной функции называются видом маркеров заголовка запроса, и маркер аутентификации, то вызов разрешается, если нет проблем

Это общая идея, раздел функция зрения последующие вызовы для защиты рук, как до , так и после любой операции до конца завершить, может выполняться по мере необходимости для достижения.
В следующих разделах в соответствии с порядком выше идеи, показать основной код, код завершается , наконец , отправил.

Конкретные шаги

Настройка Inter колба

Предпочтительные передние и задние концы разделены между доменами должны быть сконфигурированы, задним торцевым решение проблемы, используемой здесь, библиотеки используют flask_cors, следующий образом:

Будет ли быть из-за передней части каждого запроса HTTP после получения маркер маркер, предоставленный в голове, для данного имени I «токенов», если используются другие имена, которые будут заменены в «Access-Control-Allow-Headers» в

from flask_cors import CORS

CORS(app,supports_credentials=True)
@app.after_request
def after_request(resp):
    resp = make_response(resp)
    resp.headers['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8080'
    resp.headers['Access-Control-Allow-Methods'] = 'GET,POST'
    resp.headers['Access-Control-Allow-Headers'] = 'content-type,token'
    return resp

Вью инициировать запрос входа в колбу через Аксиос

Передняя часть приобретенного пароля учетной записи на задний план, маркер запрашивается записью Vuex. (Vuex маркер будет написать LocalStorage)

let _this = this
axios.post('http://127.0.0.1:5000/login',{
    username:this.username,
    password:this.password,
})
.then(function(response){
    let token = response.data
    _this.changeLogin({Authorization: token})
})
.catch(function(error){
})

Колба достижения функции вида

Функция просмотра с помощью имени пользователя и пароля, информация об аутентификации пользователя и создает маркер, маркер возврата.

# Routes
@app.route('/login',methods=['POST'])
def login():
    json = request.get_json()
    user = User.query.filter_by(username = json['username']).first()
    if user.verify_password(json['password']):
        g.currnet_user = user
        token = user.generate_auth_token(expiration=3600)
        return token
    return "wrong password"

Вью конфигурации Вардар крюк

Конфигурация крюка Аксиос, во главе каждого маркера запроса HTTP, добавляются

axios.interceptors.request.use(
    config => {
        let token = localStorage.getItem('Authorization');
        if(token){
            config.headers.common['token'] = token
        }
        return config
    },
    err => {
        return Promise.reject(err);
    });

Достичь HTTPBasicAuth

flask_httpauth модуль реализует функцию очень мало, основная частью является то, что нам нужно реализовать @ auth.verify_password этой функции обратного вызова, когда @ auth.login_required модифицирована функция просмотра доступна, сначала выполнить функцию обратного вызова, получить в функции обратного вызова маркер головы HTTP, и убедитесь, что маркер является законным, если оно юридически разрешен доступ.

from flask_httpauth import HTTPBasicAuth
auth = HTTPBasicAuth()

@auth.verify_password
def verify_password(username_token):
    username_token = request.headers.get('Token')
    if username_token == '':
        return False
    else:
        g.currnet_user = User.verify_auth_token(username_token)
        g.token_used = True
        return g.currnet_user is not None

@auth.login_required
@app.route('/creatpost',methods=['POST'])
def new_post():
    json = request.get_json()
    newpost = Post(title=json['title'],content=json['content'])
    db.session.add(newpost)
    db.session.commit()
    return "200 OK"

замечание

Исходя из вышеизложенных раздела кода, который является ядром символического управления, и более осведомленные идей читать код, потому что это также является причина для вызова функций, таких как ОРМ, так только по части функции коды не является совершенной, пожалуйста, обратитесь к упрощать следующее после полный код.

Полный код

Он подчеркнул : Следующий код для простоты кода , необходимого для реализации самых основных функций, а не следовать нормам.

колба

import os
from flask import Flask,make_response,render_template,redirect,url_for,jsonify,g,current_app,request,session
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
from flask_httpauth import HTTPBasicAuth
from flask_login import login_user,UserMixin,LoginManager,login_required
from werkzeug.security import generate_password_hash,check_password_hash
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer

basedir = os.path.abspath(os.path.dirname(__file__))

# SQLite
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret-key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir,'data.sqlite')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

# CORS
CORS(app,supports_credentials=True)
@app.after_request
def after_request(resp):
    resp = make_response(resp)
    resp.headers['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8080'
    resp.headers['Access-Control-Allow-Methods'] = 'GET,POST'
    resp.headers['Access-Control-Allow-Headers'] = 'content-type,token'
    return resp

# Http auth
auth = HTTPBasicAuth()

@auth.verify_password
def verify_password(username_token):
    username_token = request.headers.get('Token')
    if username_token == '':
        return False
    else:
        g.currnet_user = User.verify_auth_token(username_token)
        g.token_used = True
        return g.currnet_user is not None

@auth.error_handler
def auth_error():
    return unauthorized('Invalid credentials')

# Routes
@app.route('/login',methods=['POST'])
def login():
    json = request.get_json()
    user = User.query.filter_by(username = json['username']).first()
    if user.verify_password(json['password']):
        g.currnet_user = user
        token = user.generate_auth_token(expiration=3600)
        return token
    return "wrong password"

@app.route('/register',methods=['POST'])
def register():
    json = request.get_json()
    email = json['username'] + '@email.com'
    user = User(email=email,username=json['username'],password=json['password'])
    db.session.add(user)
    db.session.commit()
    return "200 OK register"

@app.route('/postlist')
def article():
    ptemp = Post.query.all()
    return jsonify({
            'posts': [post.to_json() for post in ptemp],
        })

@auth.login_required
@app.route('/creatpost',methods=['POST'])
def new_post():
    json = request.get_json()
    newpost = Post(title=json['title'],content=json['content'])
    db.session.add(newpost)
    db.session.commit()
    return "200 OK"

def unauthorized(message):
    response = jsonify({'error': 'unauthorized', 'message': message})
    response.status_code = 401
    return response

# ORM
class User(UserMixin,db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(64),unique=True,index=True)
    username = db.Column(db.String(64),unique=True,index=True)
    password_hash = db.Column(db.String(128))

    @property
    def password(self):
        raise AttributeError('password is not a readable attribute')

    @password.setter
    def password(self,password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self,password):
        return check_password_hash(self.password_hash,password)

    def generate_auth_token(self,expiration):
        s = Serializer(current_app.config['SECRET_KEY'],expires_in = expiration)
        return  s.dumps({'id':self.id}).decode('utf-8')

    @staticmethod
    def verify_auth_token(token):
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            data = s.loads(token)
        except:
            return None
        return User.query.get(data['id'])

class Post(db.Model):
    __tablename__ = 'posts'
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(64),unique=True,index=True)
    content = db.Column(db.String(64))

    def to_json(self):
        json_post = {
            'title': self.title,
            'content': self.content,
        }
        return json_post

if __name__ == '__main__':
    db.drop_all()
    db.create_all()
    app.run()

Вид - main.js

import Vue from 'vue';
import App from './App.vue';
import VueRouter from 'vue-router';
import router from './router';
import iView from 'iview';
import 'iview/dist/styles/iview.css';
import axios from 'axios';
import vueAxios from 'vue-axios';
import store from './store';
import Vuex from 'vuex'

Vue.config.productionTip = false

Vue.use(VueRouter)
Vue.use(iView)
Vue.use(vueAxios,axios)
Vue.use(Vuex)

router.afterEach(route=>{
    window.scroll(0,0);
})

router.beforeEach((to,from,next)=>{
    let token = localStorage.getItem('Authorization');
    if(!to.meta.isLogin){
        next()
    }else{
        let token = localStorage.getItem('Authorization');
        if(token == null || token == ''){
            next('/')
        }else{
            next()
        }
    }
})

axios.interceptors.request.use(
    config => {
        let token = localStorage.getItem('Authorization');
        if(token){
            config.headers.common['token'] = token
        }
        return config
    },
    err => {
        return Promise.reject(err);
    });

new Vue({
  el:'#app',
  render: h => h(App),
  router,
  store,
})

Вид - Vuex

import Vue from 'vue';
import Vuex from 'vuex';
import store from './index';

Vue.use(Vuex);

export default new Vuex.Store({
    state:{
        Authorization: localStorage.getItem('Authorization') ? localStorage.getItem('Authorization') : ''
    },
    mutations:{
        changeLogin (state, user) {
            state.Authorization = user.Authorization;
            localStorage.setItem('Authorization', user.Authorization);
        }
    },
})

Вю - маршрутизатор

import Vue from 'vue'
import Router from 'vue-router'

import home from '../components/home.vue'
import articleDetail from '../components/articleDetail'
import createPost from '../components/createPost'

Vue.use(Router)
export default new Router({
    mode:'history',
    routes:[
        {
            path:'/',
            component:home,
            name:'home',
            meta:{
                isLogin:false
            }
        },
        {
            path:'/article',
            component:articleDetail,
            name:'article',
            meta:{
                isLogin:false
            }
        },
        {
            path:'/createpost',
            component:createPost,
            name:'createpost',
            meta:{
                isLogin:true
            }
        },
    ]
})

Вид - Компоненты - home.vue

<template>
    <div class="super">
        <div class="header">
            <div class="buttomDiv">
                <Button type="success" class="loginButton" @click="showLoginModal">Login</Button>
                <Button type="primary" class="loginButton" @click="showRegisterModal">Register</Button>
            </div>
        </div>

        <div class = "content">
            <div class="contentLeft">
                <div
                    v-for = "post in blogList"
                    >
                    <thumbnail 
                        v-bind:title=post.title
                        v-bind:content=post.content
                    ></thumbnail>
                </div>
            </div>
            <div class="contentRight"></div>

        </div>

        <Modal v-model="registerModalStatus" @on-ok="registerEvent">
            <p>Register</p>
            <Input v-model="username" placeholder="Username" style="width: 300px" />
            <Input v-model="password" placeholder="Password" style="width: 300px" />
        </Modal>

        <Modal v-model="loginModalStatus" @on-ok="loginEvent">
            <p>Login</p>
            <Input v-model="username" placeholder="Username" style="width: 300px" />
            <Input v-model="password" placeholder="Password" style="width: 300px" />
        </Modal>

    </div>
</template>

<script>
    import axios from 'axios'
    import {mapMutations} from 'vuex'
    import store from '../store'
    import thumbnail from './articleThumbnail.vue'

    export default{
        name: 'home',
        data:function(){
            return {
                loginModalStatus:false,
                registerModalStatus:false,
                username:'',
                password:'',
                blogList:'',
            }
        },
        components:{
            thumbnail:thumbnail,
        },
        created(){
            localStorage.removeItem("Authorization","")
            let _this = this
            axios.get('http://127.0.0.1:5000/postlist')
                    .then(function(response){
                        _this.blogList = response.data.posts
                    })
                    .catch(function(error){
                    })
        },
        methods:{
            ...mapMutations([
                'changeLogin'
            ]),
            showRegisterModal:function(){
                this.registerModalStatus = true;
            },
            showLoginModal:function(){
                this.loginModalStatus = true;
            },
            registerEvent:function(){
                let that = this
                axios.post('http://127.0.0.1:5000/register',{
                    username:this.username,
                    password:this.password,
                    })
                .then(function(res){

                })
                .catch(function(error){

                })
            },
            loginEvent:function(){
                let _this = this
                axios.post('http://127.0.0.1:5000/login',{
                            username:this.username,
                            password:this.password,
                        })
                    .then(function(response){
                        let token = response.data
                        _this.changeLogin({Authorization: token})
                    })
                    .catch(function(error){
                    })
            },
            navigator:function(){
                this.$router.push("/article")
            },

        },
    }
</script>

<style scoped>

</style>

постскриптум

Полный код адреса GitHub
haythamBlog
haythamBlog_flask

####
Для более Haytham оригинальных статей, пожалуйста , обратите внимание на общедоступный номер «Xuju Long»:
Мой микро-общественный канал номер

рекомендация

отblog.51cto.com/13852791/2438066
рекомендация