parent
ac16c46e01
commit
09a2c47edc
@ -1,27 +1,27 @@ |
|||||||
from datetime import datetime,timedelta |
from datetime import datetime,timedelta |
||||||
from uuid import uuid1 |
from uuid import uuid1 |
||||||
import secrets |
import secrets |
||||||
|
|
||||||
class Nounce(object): |
class Nounce(object): |
||||||
def __init__(self): |
def __init__(self): |
||||||
self.id = uuid1() |
self.id = uuid1() |
||||||
self.expiration = datetime.now()+timedelta(seconds=60) |
self.expiration = datetime.now()+timedelta(seconds=60) |
||||||
self.token = secrets.token_urlsafe() |
self.token = secrets.token_urlsafe() |
||||||
|
|
||||||
def expired(self): |
def expired(self): |
||||||
return datetime.now() > self.expiration |
return datetime.now() > self.expiration |
||||||
|
|
||||||
def bump(self): |
def bump(self): |
||||||
self.expiration = datetime.now()+timedelta(seconds=60) |
self.expiration = datetime.now()+timedelta(seconds=60) |
||||||
|
|
||||||
class AuthSession(object): |
class AuthSession(object): |
||||||
def __init__(self, username): |
def __init__(self, username): |
||||||
self.id = uuid1() |
self.id = uuid1() |
||||||
self.expiration = datetime.now()+timedelta(minutes=30) |
self.expiration = datetime.now()+timedelta(minutes=30) |
||||||
self.username = username |
self.username = username |
||||||
|
|
||||||
def expired(self): |
def expired(self): |
||||||
return datetime.now() > self.expiration |
return datetime.now() > self.expiration |
||||||
|
|
||||||
def bumpExpiration(self): |
def bumpExpiration(self): |
||||||
self.expiration = datetime.now()+timedelta(minutes=30) |
self.expiration = datetime.now()+timedelta(minutes=30) |
||||||
@ -1,19 +1,19 @@ |
|||||||
#!/usr/bin/env python3 |
#!/usr/bin/env python3 |
||||||
from flask import * |
from flask import * |
||||||
import secrets |
import secrets |
||||||
import nonce |
import nonce |
||||||
import os.path |
import os.path |
||||||
|
|
||||||
app = Flask(__name__) |
app = Flask(__name__) |
||||||
app.secret_key = secrets.token_urlsafe() |
app.secret_key = secrets.token_urlsafe() |
||||||
app.register_blueprint(nonce.app) |
app.register_blueprint(nonce.app) |
||||||
|
|
||||||
ROUTES = {'routes': ['/', '/nonce'] } |
ROUTES = {'routes': ['/', '/nonce'] } |
||||||
@app.route('/') |
@app.route('/') |
||||||
def home(): |
def home(): |
||||||
return jsonify(ROUTES) |
return jsonify(ROUTES) |
||||||
|
|
||||||
nonce.loadUsers( os.path.join('data','userlist.json') ) |
nonce.loadUsers( os.path.join('data','userlist.json') ) |
||||||
if __name__ == '__main__': |
if __name__ == '__main__': |
||||||
app.run( host='0.0.0.0', port=7070) |
app.run( host='0.0.0.0', port=7070) |
||||||
|
|
||||||
|
|||||||
@ -1,179 +1,179 @@ |
|||||||
<!doctype html> |
<!doctype html> |
||||||
<html> |
<html> |
||||||
<head> |
<head> |
||||||
<script |
<script |
||||||
src="https://code.jquery.com/jquery-3.4.1.min.js" |
src="https://code.jquery.com/jquery-3.4.1.min.js" |
||||||
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" |
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" |
||||||
crossorigin="anonymous"></script> |
crossorigin="anonymous"></script> |
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsSHA/2.3.1/sha256.js" |
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsSHA/2.3.1/sha256.js" |
||||||
integrity="sha384-rxrcz1OyCVG21aEKlNBwgap2/r4pSV/RrN6eEMQhLriiTZnnzhCFZr+ZKGPJNSJX" |
integrity="sha384-rxrcz1OyCVG21aEKlNBwgap2/r4pSV/RrN6eEMQhLriiTZnnzhCFZr+ZKGPJNSJX" |
||||||
crossorigin="anonymous"></script> |
crossorigin="anonymous"></script> |
||||||
|
|
||||||
<script> |
<script> |
||||||
|
|
||||||
function generateCnonce() { |
function generateCnonce() { |
||||||
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
||||||
var text = ""; |
var text = ""; |
||||||
for(var i = 0; i < 43; i++) { |
for(var i = 0; i < 43; i++) { |
||||||
text += possible.charAt(Math.floor(Math.random() * possible.length)); |
text += possible.charAt(Math.floor(Math.random() * possible.length)); |
||||||
} |
} |
||||||
return text; |
return text; |
||||||
} |
} |
||||||
|
|
||||||
function submit() { |
function submit() { |
||||||
var user = $("#user").val(); |
var user = $("#user").val(); |
||||||
var pwd = $("#pwd").val(); |
var pwd = $("#pwd").val(); |
||||||
jQuery.get( 'nonce', {}, function(data){ |
jQuery.get( 'nonce', {}, function(data){ |
||||||
var nonce = data.token; |
var nonce = data.token; |
||||||
var cnonce = generateCnonce(); |
var cnonce = generateCnonce(); |
||||||
|
|
||||||
var sha256 = new jsSHA('SHA-256', 'TEXT'); //B64 |
var sha256 = new jsSHA('SHA-256', 'TEXT'); //B64 |
||||||
sha256.update(pwd); |
sha256.update(pwd); |
||||||
var pwdHashed_sha256 = sha256.getHash('HEX') |
var pwdHashed_sha256 = sha256.getHash('HEX') |
||||||
|
|
||||||
sha256 = new jsSHA('SHA-256', 'TEXT'); |
sha256 = new jsSHA('SHA-256', 'TEXT'); |
||||||
sha256.update( pwdHashed_sha256+cnonce+nonce ); |
sha256.update( pwdHashed_sha256+cnonce+nonce ); |
||||||
const pwdhash= sha256.getHash('HEX') |
const pwdhash= sha256.getHash('HEX') |
||||||
const payload = { |
const payload = { |
||||||
user: user, |
user: user, |
||||||
cnonce: cnonce, |
cnonce: cnonce, |
||||||
pwdhash: pwdhash |
pwdhash: pwdhash |
||||||
} |
} |
||||||
jQuery.post('login', payload, |
jQuery.post('login', payload, |
||||||
function(data){ |
function(data){ |
||||||
location.href = '/'; |
location.href = '/'; |
||||||
} |
} |
||||||
).fail(function() { |
).fail(function() { |
||||||
var el = $('.error_msg'); |
var el = $('.error_msg'); |
||||||
el.css('animation-name',''); |
el.css('animation-name',''); |
||||||
void el[0].offsetWidth; //trigger reflow |
void el[0].offsetWidth; //trigger reflow |
||||||
el.css('animation-name','fade'); |
el.css('animation-name','fade'); |
||||||
}); |
}); |
||||||
} ); |
} ); |
||||||
} |
} |
||||||
|
|
||||||
$( document ).ready(function() { |
$( document ).ready(function() { |
||||||
$("body").keypress( function(e) { |
$("body").keypress( function(e) { |
||||||
if(e.key=='Enter') { |
if(e.key=='Enter') { |
||||||
submit(); |
submit(); |
||||||
} |
} |
||||||
}); |
}); |
||||||
$("#login").click( submit ); |
$("#login").click( submit ); |
||||||
}); |
}); |
||||||
</script> |
</script> |
||||||
<style> |
<style> |
||||||
input { |
input { |
||||||
border: 1px solid lightgray; |
border: 1px solid lightgray; |
||||||
border-radius: 5px; |
border-radius: 5px; |
||||||
padding: 5px 5px 5px 5px; |
padding: 5px 5px 5px 5px; |
||||||
/*width: 150px;*/ |
/*width: 150px;*/ |
||||||
width:100%; |
width:100%; |
||||||
display: block; |
display: block; |
||||||
margin: 1px auto 3px auto; |
margin: 1px auto 3px auto; |
||||||
box-sizing: border-box; |
box-sizing: border-box; |
||||||
} |
} |
||||||
|
|
||||||
button { |
button { |
||||||
border: none; |
border: none; |
||||||
border-radius: 5px; |
border-radius: 5px; |
||||||
padding: 5px 5px 5px 5px; |
padding: 5px 5px 5px 5px; |
||||||
/*width: 150px;*/ |
/*width: 150px;*/ |
||||||
width:100%; |
width:100%; |
||||||
display: block; |
display: block; |
||||||
margin: 1px auto 3px auto; |
margin: 1px auto 3px auto; |
||||||
box-shadow: 0px 1px 3px 0px rgba(0,0,0,0.75); |
box-shadow: 0px 1px 3px 0px rgba(0,0,0,0.75); |
||||||
cursor: pointer; |
cursor: pointer; |
||||||
} |
} |
||||||
|
|
||||||
button:hover { |
button:hover { |
||||||
background-color: lightgray; |
background-color: lightgray; |
||||||
} |
} |
||||||
|
|
||||||
button:active { |
button:active { |
||||||
transform: translateY(1px); |
transform: translateY(1px); |
||||||
box-shadow: 0px 1px 2px 0px rgba(0,0,0,0.75); |
box-shadow: 0px 1px 2px 0px rgba(0,0,0,0.75); |
||||||
} |
} |
||||||
|
|
||||||
button:focus { |
button:focus { |
||||||
outline: 0; |
outline: 0; |
||||||
} |
} |
||||||
|
|
||||||
.error_msg { |
.error_msg { |
||||||
border: none; |
border: none; |
||||||
border-radius: 5px; |
border-radius: 5px; |
||||||
display: block; |
display: block; |
||||||
background-color: #CC3333; |
background-color: #CC3333; |
||||||
color: white; |
color: white; |
||||||
animation-duration: 2.5s; |
animation-duration: 2.5s; |
||||||
opacity: 0; |
opacity: 0; |
||||||
padding: 5px; |
padding: 5px; |
||||||
width:100%; |
width:100%; |
||||||
box-sizing: border-box; |
box-sizing: border-box; |
||||||
font: 400 13.3333px Arial; |
font: 400 13.3333px Arial; |
||||||
font-weight: 600; |
font-weight: 600; |
||||||
text-align: center; |
text-align: center; |
||||||
margin: 1px auto 3px auto; |
margin: 1px auto 3px auto; |
||||||
} |
} |
||||||
|
|
||||||
@keyframes fade { |
@keyframes fade { |
||||||
0% {opacity: 1;} |
0% {opacity: 1;} |
||||||
25% {opacity: 1;} |
25% {opacity: 1;} |
||||||
100% {opacity: 0;} |
100% {opacity: 0;} |
||||||
} |
} |
||||||
|
|
||||||
.centered { |
.centered { |
||||||
width: 180px; |
width: 180px; |
||||||
margin: 0; |
margin: 0; |
||||||
position: absolute; |
position: absolute; |
||||||
top: 50%; |
top: 50%; |
||||||
left: 50%; |
left: 50%; |
||||||
transform: translate(-50%, -50%); |
transform: translate(-50%, -50%); |
||||||
} |
} |
||||||
|
|
||||||
body { |
body { |
||||||
background: |
background: |
||||||
linear-gradient(27deg, |
linear-gradient(27deg, |
||||||
#151515 5px, |
#151515 5px, |
||||||
transparent 5px |
transparent 5px |
||||||
) 0 5px, |
) 0 5px, |
||||||
linear-gradient(207deg, |
linear-gradient(207deg, |
||||||
#151515 5px, |
#151515 5px, |
||||||
transparent 5px |
transparent 5px |
||||||
) 10px 0px, |
) 10px 0px, |
||||||
linear-gradient(27deg, |
linear-gradient(27deg, |
||||||
#222 5px, |
#222 5px, |
||||||
transparent 5px |
transparent 5px |
||||||
) 0px 10px, |
) 0px 10px, |
||||||
linear-gradient(207deg, |
linear-gradient(207deg, |
||||||
#222 5px, |
#222 5px, |
||||||
transparent 5px |
transparent 5px |
||||||
) 10px 5px, |
) 10px 5px, |
||||||
linear-gradient(90deg, |
linear-gradient(90deg, |
||||||
#1b1b1b 10px, |
#1b1b1b 10px, |
||||||
transparent 10px |
transparent 10px |
||||||
), |
), |
||||||
linear-gradient( |
linear-gradient( |
||||||
#1d1d1d 25%, |
#1d1d1d 25%, |
||||||
#1a1a1a 25%, |
#1a1a1a 25%, |
||||||
#1a1a1a 50%, |
#1a1a1a 50%, |
||||||
transparent 50%, |
transparent 50%, |
||||||
transparent 75%, |
transparent 75%, |
||||||
#242424 75%, |
#242424 75%, |
||||||
#242424 |
#242424 |
||||||
); |
); |
||||||
background-color: #131313; |
background-color: #131313; |
||||||
background-size: 20px 20px; |
background-size: 20px 20px; |
||||||
background-clip: content-box; |
background-clip: content-box; |
||||||
} |
} |
||||||
|
|
||||||
</style> |
</style> |
||||||
</head> |
</head> |
||||||
<body> |
<body> |
||||||
<div class="centered"> |
<div class="centered"> |
||||||
<input id="user" type="text" /> |
<input id="user" type="text" /> |
||||||
<input id="pwd" type="password" /> |
<input id="pwd" type="password" /> |
||||||
<button id="login">Login</button> |
<button id="login">Login</button> |
||||||
<div class="error_msg">Login failed!</div> |
<div class="error_msg">Login failed!</div> |
||||||
</div> |
</div> |
||||||
</body> |
</body> |
||||||
</html> |
</html> |
||||||
Loading…
Reference in new issue