浏览代码

login auth

aaron-1015 3 年之前
父节点
当前提交
94f7df896f
共有 6 个文件被更改,包括 120 次插入134 次删除
  1. 二进制
      __pycache__/main.cpython-37.pyc
  2. 二进制
      __pycache__/models.cpython-37.pyc
  3. 106 4
      main.py
  4. 13 0
      models.py
  5. 0 129
      static/index.js
  6. 1 1
      templates/login.html

二进制
__pycache__/main.cpython-37.pyc


二进制
__pycache__/models.cpython-37.pyc


+ 106 - 4
main.py

@@ -1,5 +1,5 @@
 # fastapi
-from fastapi import FastAPI, Request, Response, HTTPException
+from fastapi import FastAPI, Request, Response, HTTPException, status, Depends
 from fastapi import templating
 from fastapi.templating import Jinja2Templates
 from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
@@ -16,14 +16,17 @@ import os
 
 # time
 import datetime
+from datetime import timedelta
 
 # db
 import dataset
 from passlib import context
+import models
 
 # authorize
 from passlib.context import CryptContext
-# from jose import JWTError, jwt
+pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
+from jose import JWTError, jwt
 from fastapi_jwt_auth import AuthJWT
 from fastapi_jwt_auth.exceptions import AuthJWTException
 from fastapi.security import OAuth2AuthorizationCodeBearer, OAuth2PasswordRequestForm
@@ -31,8 +34,19 @@ from fastapi.security import OAuth2AuthorizationCodeBearer, OAuth2PasswordReques
 
 # app
 app = FastAPI()
+app.add_middleware(
+    CORSMiddleware,
+    allow_origins=["*"],
+    allow_credentials=True,
+    allow_methods=["*"],
+    allow_headers=["*"],
+)
 
 
+SECRET_KEY = "df2f77bd544240801a048bd4293afd8eeb7fff3cb7050e42c791db4b83ebadcd"
+ALGORITHM = "HS256"
+ACCESS_TOKEN_EXPIRE_MINUTES = 3000
+pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
 
 # 
 app.mount(path='/templates', app=StaticFiles(directory='templates'), name='templates')
@@ -59,13 +73,41 @@ async def index(request: Request):
 async def login(request: Request):
     return templates.TemplateResponse(name='login.html', context={'request': request})
 
+
+@app.post("/login")
+async def login_for_access_token(request: Request, form_data: OAuth2PasswordRequestForm = Depends(), Authorize: AuthJWT = Depends()):
+    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/aaron_testdb?charset=utf8mb4')
+    user = authenticate_user(form_data.username, form_data.password)
+    if not user:
+        raise HTTPException(
+            status_code=status.HTTP_401_UNAUTHORIZED,
+            detail="Incorrect username or password",
+            headers={"WWW-Authenticate": "Bearer"},
+        )
+    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
+    access_token = create_access_token(
+        data={"sub": user.username}, expires_delta=access_token_expires
+    )
+    table = db['users']
+    user.token = access_token
+    table.update(dict(user), ['username'])
+    access_token = Authorize.create_access_token(subject=user.username)
+    refresh_token = Authorize.create_refresh_token(subject=user.username)
+    Authorize.set_access_cookies(access_token)
+    Authorize.set_refresh_cookies(refresh_token)
+    #return templates.TemplateResponse("index.html", {"request": request, "msg": 'Login'})
+    return {"access_token": access_token, "token_type": "bearer"}
+
+    
+
+
 @app.get('/home', response_class=HTMLResponse)
 async def login(request: Request):
     return templates.TemplateResponse(name='home.html', context={'request': request})
 
 @app.get('/monitor/tower', response_class=HTMLResponse)
 async def login(request: Request):
-    return templates.TemplateResponse(name='home.html', context={'request': request})
+    return templates.TemplateResponse(name='tower.html', context={'request': request})
 
 @app.get('/optim', response_class=HTMLResponse)
 async def login(request: Request):
@@ -85,4 +127,64 @@ async def login(request: Request):
 
 @app.get('/set_up/system', response_class=HTMLResponse)
 async def login(request: Request):
-    return templates.TemplateResponse(name='system.html', context={'request': request})
+    return templates.TemplateResponse(name='system.html', context={'request': request})
+
+
+
+
+
+
+
+# Login funtion part
+def check_user_exists(username):
+    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/aaron_testdb?charset=utf8mb4')
+    if int(next(iter(db.query('SELECT COUNT(*) FROM aaron_testdb.user WHERE username = "'+username+'"')))['COUNT(*)']) > 0:
+        return True
+    else:
+        return False
+
+def get_user(username: str):
+    """ 取得使用者資訊(Model) """
+    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/aaron_testdb?charset=utf8mb4')
+    if not check_user_exists(username):  # if user don't exist
+        return False
+    user_dict = next(
+        iter(db.query('SELECT * FROM aaron_testdb.user where username ="'+username+'"')))
+    user = models.User(**user_dict)
+    return user
+    
+# def user_register(user):
+#     db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/aaron_testdb?charset=utf8mb4')
+#     table = db['users']
+#     user.password = get_password_hash(user.password)
+#     table.insert(dict(user))
+
+def get_password_hash(password):
+    """ 加密密碼 """
+    return pwd_context.hash(password)
+
+def verify_password(plain_password, hashed_password):
+    """ 驗證密碼(hashed) """
+    return pwd_context.verify(plain_password, hashed_password)
+
+def authenticate_user(username: str, password: str):
+    """ 連線DB,讀取使用者是否存在。 """
+    db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/aaron_testdb?charset=utf8mb4')
+    if not check_user_exists(username):  # if user don't exist
+        return False
+    user_dict = next(iter(db.query('SELECT * FROM aaron_testdb.user where username ="'+username+'"')))
+    user = models.User(**user_dict)
+    if not verify_password(password, user.password):
+        return False
+    return user
+
+def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
+    """ 創建token,並設定過期時間。 """
+    to_encode = data.copy()
+    if expires_delta:
+        expire = datetime.utcnow() + expires_delta
+    else:
+        expire = datetime.utcnow() + timedelta(minutes=15)
+    to_encode.update({"exp": expire})
+    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
+    return encoded_jwt

+ 13 - 0
models.py

@@ -0,0 +1,13 @@
+from pydantic import BaseModel
+from typing import Optional
+import datetime
+
+
+class User(BaseModel):
+    userName: str
+    userPassword: str
+    changPwdTime: Optional[datetime.datetime] = None
+    isAdmin: Optional[bool] = None
+    isEnable: Optional[bool] = True
+    updateTime: Optional[datetime.datetime] = None
+    token: Optional[str] = None

+ 0 - 129
static/index.js

@@ -1,129 +0,0 @@
-// //設定cookie
-// function setCookie(name,value)
-// {
-//     var Days = 30;
-//     var exp = new Date();
-//     exp.setTime(exp.getTime() + Days*24*60*60*1000);
-//     document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();
-// }
-
-// //獲取cookie
-// function getCookie(name)
-// {
-//     var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
-//     if(arr=document.cookie.match(reg))
-//     return unescape(arr[2]);
-//     else
-//     return null;
-// }
-
-// //setCookie('lan','hk');    繁體中文
-// //setCookie('lan','en');    英文
-
-// var zh = {
-//     "title" : "中文Title",
-//     "info" : "中文info",
-//     "login" : "中文Login",
-//     "choose_character": "中文choose_character"
-// };
-
-// var hk = {
-//     "title" : "hk Title",
-//     "info" : "hk info",
-//     "login" : "hk Login",
-//     "choose_character": "hk choose_character"
-// };
-
-// var en = {
-//     "title" : "英文Title",
-//     "info" : "英文info",
-//     "login" : "英文Login",
-//     "choose_character": "英文choose_character"
-// };
-
-
-
-// // 4. 轉換
-// function changeLan(val) {
-//     var val = val.value;
-//     setCookie('lan', val);
-//     $('[set-lan]').each(function(){
-//         var me = $(this);
-//         var a = me.attr('set-lan').split(':');
-//         var p = a[0];   //文字放置位置
-//         var m = a[1];   //文字標示
-        
-//         //用選擇語言後保存在cookie中,這裡讀取cooikes的語言版本
-//         var lan = getCookie('lan');
-//         console.log(lan);
-    
-//         //選取語言文字
-//         switch(lan){
-//             case 'zh':
-//                 var t = zh[m];  
-//                 console.log(t);
-//                 break;
-//             case 'en':
-//                 var t = en[m];
-//                 console.log(t);
-//                 break;
-//             default:
-//                 var t = hk[m];
-//                 console.log(t);
-//         }
-    
-//         //所選語言沒有就換
-//         if(t==undefined) t = zh[m];
-//         if(t==undefined) t = en[m];
-//         if(t==undefined) t = hk[m];
-    
-//         if(t==undefined) return true;   //都沒有就跳出
-    
-//         //文字放置位置有(html,val等,可以自己添加)
-//         switch(p){
-//             case 'html':
-//                 me.html(t);
-//                 break;
-//             case 'val':
-//             case 'value':
-//                 me.val(t);
-//                 break;
-//             default:
-//                 me.html(t);
-//         }
-    
-//     });
-// }
-
-
-
-// // js裡面的轉換
-// function get_lan(m)
-// {
-//     //獲取文字
-//     var lan = getCookie('lan');     //語言版本
-//     //選取語言文字
-//     switch(lan){
-//         case 'zh':
-//             var t = zh[m];
-//             break;
-//         case 'hk':
-//             var t = hk[m];
-//             break;
-//         default:
-//             var t = en[m];
-//     }
-
-//     //如果沒有找到就轉換其他語言
-//     if(t==undefined) t = zh[m];
-//     if(t==undefined) t = en[m];
-//     if(t==undefined) t = hk[m];
-
-//     if(t==undefined) t = m; //如果還是沒有就直接用標示
-
-//     return t;
-// }
-
-
-// // 
-// changeLan('zh');

+ 1 - 1
templates/login.html

@@ -15,7 +15,7 @@
             <input type="password" class="form-control" id="password" name="password"  placeholder="請輸入密碼">
         </div>
         <div class="d-flex justify-content-center">
-            <button type="submit" class="btn btn-primary align-items-center">登入</button>
+            <button type="submit" class="btn btn-primary align-items-center" id="btn_login">登入</button>
         </div>
 
     </form>