указательный столб
В соответствии с тем, что ключевыми словами, этот блог возможно поможет
- Не использовать фабричные функции КОЛБУ приложения
- Применение Настой не использует план
- Колба конфигурации поперечного домена
- Токен управление государством на основе логина
- Колба + Вью
- Вьет перехват маршрутизации
- Вардар крюк
Применяемая сцена
Это личный блог, чтобы построить блог записи, является простым и колба Вью на «книги», окончательный код будет включать в себя веб-разработчики часто используемые функции. (Неполный, для использования относительно высокой частоты, за исключением)
окружающая среда
- Система: не зависит от
- Колба (python3)
- Вью (Node.js)
ссылка
«Реальное развитие Колба Веб - разработка на Python на основе веб - приложения»
Vue.js
фон
Личные решения блог так много, то почему я должен строить себя это?
На самом деле, цель состоит в том, чтобы не создавать личный блог написанный непосредственно с помощью WordPress блог ... или личный блог , но я хотел , чтобы практиковать эту технологию они учатся, принимая во внимание будущее может присоединиться к балансировки нагрузки, методы кластеризации, что приводит к существенным изменениям в архитектуре или попробовать голосовое управление и другие новые игры играют, код построчно из о целесообразности операции обязательно лучше.
Код функции
Функция Блог не является совершенным, только для достижения следующих основных функций
Спереди: Регистрация Вход, создание блога (уценки редактор) Главная тянуть все статьи, создать блог , нужно войти в состояние.
Сзади: услуга требует больше функции просмотра, конфигураций междоменных, маркер управления и аутентификации, управления базами данных.
Для целей записей обмена добьетесь вошли в управляемом коде можно резюмировать следующим образом
Реализация идей
Для осуществления государственного управления на основе маркера входа в систему, идея заключается в следующем
- Пароль учетной записи переднего конца представить фон
- Фон проверки, с помощью этого маркера возвращается
- Перед тем как на переднем конце каждого запроса маркера, который предусмотрен для запроса заголовка (используется Аксиос крючков)
- Предпосылки приобретения защищенной функции называются видом маркеров заголовка запроса, и маркер аутентификации, то вызов разрешается, если нет проблем
Это общая идея, раздел функция зрения последующие вызовы для защиты рук, как до , так и после любой операции до конца завершить, может выполняться по мере необходимости для достижения.
В следующих разделах в соответствии с порядком выше идеи, показать основной код, код завершается , наконец , отправил.
Конкретные шаги
Настройка 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»: