Browse Source

login auth

aaron-1015 3 years ago
parent
commit
94f7df896f
6 changed files with 120 additions and 134 deletions
  1. BIN
      __pycache__/main.cpython-37.pyc
  2. BIN
      __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

BIN
__pycache__/main.cpython-37.pyc


BIN
__pycache__/models.cpython-37.pyc


+ 106 - 4
main.py

@@ -1,5 +1,5 @@
 # fastapi
 # fastapi
-from fastapi import FastAPI, Request, Response, HTTPException
+from fastapi import FastAPI, Request, Response, HTTPException, status, Depends
 from fastapi import templating
 from fastapi import templating
 from fastapi.templating import Jinja2Templates
 from fastapi.templating import Jinja2Templates
 from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
 from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
@@ -16,14 +16,17 @@ import os
 
 
 # time
 # time
 import datetime
 import datetime
+from datetime import timedelta
 
 
 # db
 # db
 import dataset
 import dataset
 from passlib import context
 from passlib import context
+import models
 
 
 # authorize
 # authorize
 from passlib.context import CryptContext
 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 import AuthJWT
 from fastapi_jwt_auth.exceptions import AuthJWTException
 from fastapi_jwt_auth.exceptions import AuthJWTException
 from fastapi.security import OAuth2AuthorizationCodeBearer, OAuth2PasswordRequestForm
 from fastapi.security import OAuth2AuthorizationCodeBearer, OAuth2PasswordRequestForm
@@ -31,8 +34,19 @@ from fastapi.security import OAuth2AuthorizationCodeBearer, OAuth2PasswordReques
 
 
 # app
 # app
 app = FastAPI()
 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')
 app.mount(path='/templates', app=StaticFiles(directory='templates'), name='templates')
@@ -59,13 +73,41 @@ async def index(request: Request):
 async def login(request: Request):
 async def login(request: Request):
     return templates.TemplateResponse(name='login.html', context={'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)
 @app.get('/home', response_class=HTMLResponse)
 async def login(request: Request):
 async def login(request: Request):
     return templates.TemplateResponse(name='home.html', context={'request': request})
     return templates.TemplateResponse(name='home.html', context={'request': request})
 
 
 @app.get('/monitor/tower', response_class=HTMLResponse)
 @app.get('/monitor/tower', response_class=HTMLResponse)
 async def login(request: Request):
 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)
 @app.get('/optim', response_class=HTMLResponse)
 async def login(request: Request):
 async def login(request: Request):
@@ -85,4 +127,64 @@ async def login(request: Request):
 
 
 @app.get('/set_up/system', response_class=HTMLResponse)
 @app.get('/set_up/system', response_class=HTMLResponse)
 async def login(request: Request):
 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="請輸入密碼">
             <input type="password" class="form-control" id="password" name="password"  placeholder="請輸入密碼">
         </div>
         </div>
         <div class="d-flex justify-content-center">
         <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>
         </div>
 
 
     </form>
     </form>