提交 c236ca43 编写于 作者: 梦境迷离's avatar 梦境迷离

Add cookie support

上级 f17cc0eb
......@@ -58,6 +58,7 @@ var host = "192.168.124.10:8080" //改为与akka-http-server一致
更新日志
* 简单使用Base64编码支持cookie
* 实时输出在线用户数量
* 使用Akka HTTP重构WebSocket通信
* 升级Scala版本至2.12.8
......
......@@ -9,8 +9,8 @@ akka {
http.server.websocket.periodic-keep-alive-mode = pong #客户端将不会回复此类心跳
}
# 必须配置本机IP,且不能与SpringBoot绑定的相同
# 必须配置本机IP,且不能与SpringBoot绑定的相同,为了方便Akka HTTP和SpringBoot使用不同端口,使用时务必改。
akka-http-server {
host = "192.168.124.10"
host = "192.168.199.107"
port = 8080
}
\ No newline at end of file
......@@ -6,7 +6,7 @@ import java.util.List
import cn.edu.layim.constant.SystemConstant
import cn.edu.layim.domain._
import cn.edu.layim.entity.{ GroupList, User }
import cn.edu.layim.service.{ CookieService, RedisService, UserService }
import cn.edu.layim.service.{ CookieService, UserService }
import cn.edu.layim.util.{ FileUtil, SecurityUtil }
import com.github.pagehelper.PageHelper
import com.google.gson.Gson
......@@ -151,7 +151,7 @@ class UserController @Autowired()(userService: UserService, cookieService: Cooki
@RequestParam(value = "name", required = false) name: String,
@RequestParam(value = "sex", required = false) sex: Integer): String = {
val count = userService.countUsers(name, sex)
LOGGER.info("==> 总记录:" + count)
LOGGER.info(s"find users => [total = $count]")
val pages = if (count < SystemConstant.USER_PAGE) 1 else {
if (count % SystemConstant.USER_PAGE == 0) count / SystemConstant.USER_PAGE
else count / SystemConstant.USER_PAGE + 1
......@@ -260,7 +260,7 @@ class UserController @Autowired()(userService: UserService, cookieService: Cooki
@PostMapping(Array("/getOffLineMessage"))
def getOffLineMessage(request: HttpServletRequest): String = {
val user = request.getSession.getAttribute("user").asInstanceOf[User]
LOGGER.info("查询 uid = " + user.getId + " 的离线消息")
LOGGER.info(s"find offline msg [uid = ${user.getId}]")
val receives: List[Receive] = userService.findOffLineMessage(user.getId, 0)
receives.asScala.foreach {
receive => {
......@@ -324,27 +324,18 @@ class UserController @Autowired()(userService: UserService, cookieService: Cooki
@ResponseBody
@PostMapping(Array("/login"))
def login(@RequestBody user: User, request: HttpServletRequest, response: HttpServletResponse): String = {
// val userCookie = cookieService.`match`(request)
// if (userCookie != null && user != null && userCookie.getEmail.equals(user.getEmail)
// && userCookie.getPassword.equals(user.getPassword)) {
// LOGGER.info("通过 Cookie 成功登陆服务器")
// request.getSession.setAttribute("user", userCookie)
// gson.toJson(new ResultSet(userCookie))
// } else {
val u: User = userService.matchUser(user)
//未激活
if (u != null && "nonactivated".equals(u.getStatus)) {
gson.toJson(new ResultSet(SystemConstant.ERROR, SystemConstant.NONACTIVED))
} else if (u != null && !"nonactivated".equals(u.getStatus)) {
LOGGER.info(user + "成功登陆服务器")
request.getSession.setAttribute("user", u)
cookieService.addCookie(u, request, response)
gson.toJson(new ResultSet(u))
} else {
val result = new ResultSet(SystemConstant.ERROR, SystemConstant.LOGGIN_FAIL)
gson.toJson(result)
// }
val u: User = userService.matchUser(user)
//未激活
if (u != null && "nonactivated".equals(u.getStatus)) {
gson.toJson(new ResultSet(SystemConstant.ERROR, SystemConstant.NONACTIVED))
} else if (u != null && !"nonactivated".equals(u.getStatus)) {
LOGGER.info(s"user login success => [user = $user]")
request.getSession.setAttribute("user", u)
cookieService.addCookie(user, request, response)
gson.toJson(new ResultSet(u))
} else {
val result = new ResultSet(SystemConstant.ERROR, SystemConstant.LOGGIN_FAIL)
gson.toJson(result)
}
}
......@@ -526,7 +517,7 @@ class UserController @Autowired()(userService: UserService, cookieService: Cooki
def index(model: Model, request: HttpServletRequest): String = {
val user = request.getSession.getAttribute("user")
model.addAttribute("user", user)
LOGGER.info("用户" + user + "登陆服务器")
LOGGER.info(s"user access server => [user = $user]")
"index"
}
......
package cn.edu.layim.service
import java.util.Base64
import cn.edu.layim.entity.User
import cn.edu.layim.util.UUIDUtil
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.serializer.SerializerFeature
import javax.servlet.http.{ Cookie, HttpServletRequest, HttpServletResponse }
import org.slf4j.{ Logger, LoggerFactory }
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
/**
......@@ -16,40 +14,37 @@ import org.springframework.stereotype.Service
* @time 2018-10-19
*/
@Service
@deprecated
class CookieService @Autowired()(redisService: RedisService) {
class CookieService {
private final lazy val LOGGER: Logger = LoggerFactory.getLogger(classOf[CookieService])
def addCookie(user: User, request: HttpServletRequest, response: HttpServletResponse) {
val baseE: Base64.Encoder = Base64.getEncoder
val baseD: Base64.Decoder = Base64.getDecoder
//记住用户名、密码功能(注意:cookie存放密码会存在安全隐患)
val loginkeeping: String = request.getParameter("check")
if ("true".equals(loginkeeping)) {
val uID = UUIDUtil.getUUID32String()
LOGGER.info("user uuid = " + uID)
redisService.set(uID, JSON.toJSONString(user, SerializerFeature.DisableCircularReferenceDetect))
val userCookie = new Cookie("uID", uID)
if ("true" == loginkeeping) {
//使用token,通过Redis
//val uID = UUIDUtil.getUUID32String()
LOGGER.info(s"add cookie for user => [email = ${user.getEmail}]")
//简单处理,cookie key不能使用=号
val userCookie = new Cookie(new String(baseE.encode(user.getEmail.getBytes)).replace("=", ""),
new String(baseE.encode(user.getPassword.getBytes)).replace("=", ""))
userCookie.setMaxAge(30 * 24 * 60 * 60) //存活期为一个月 30*24*60*60
userCookie.setPath("/")
response.addCookie(userCookie)
}
}
def `match`(request: HttpServletRequest): User = {
val cookies = request.getCookies
//遍历所有的cookie,然后根据cookie的key值来获取value值
val uid = cookies.find(_.getName.equals("uID")).fold("")((_: Cookie).getValue)
if (uid == "")
null else {
val user = redisService.get(uid).asInstanceOf[String]
if (user != null) {
val U = JSON.parseObject(user, classOf[User])
if (U != null) {
LOGGER.info("user uuid = " + uid)
LOGGER.info("user info = " + U.toString)
U
} else null
} else null
} else {
//没有勾选时,清楚cookie
val cookies = request.getCookies;
for (cookie <- cookies) {
val cookieName = new String(baseD.decode(cookie.getName))
if (cookieName == user.getEmail) {
LOGGER.info(s"remove cookie for user => [email = ${user.getEmail}, cookie name = $cookieName]")
cookie.setMaxAge(0);
cookie.setPath("/");
response.addCookie(cookie);
}
}
}
}
}
......@@ -22,6 +22,8 @@ import scala.io.StdIn
/**
* akka-http websocket server
*
* BUG:前端初始化总会抛一个异常
*
* @author liguobin@growingio.com
* @version 1.0,2020/1/22
*/
......
<!DOCTYPE html>
<html lang="en" class="no-js"><!--<![endif]-->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>IM 登陆</title>
<link rel="shortcut icon" href="static/image/favicon.ico">
<link rel="stylesheet" type="text/css" href="static/css/login/style3.css">
<link rel="stylesheet" type="text/css" href="static/css/login/animate-custom.css">
<link rel="stylesheet" href="static/layui/css/layui.css">
<script src="/static/layui/layui.js"></script>
<style type="text/css">
body {
background: url(static/image/4.jpg) no-repeat;
background-size: cover;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1 style="color:#F0F0F0">Scala 即时通讯系统</span></h1>
</header>
<section>
<div id="container_demo">
<a class="hiddenanchor" id="toregister"></a>
<a class="hiddenanchor" id="tologin"></a>
<div id="wrapper">
<div id="login" class="animate form">
<form action="" autocomplete="on" method="post" class="layui-form" lay-filter="login">
<h1>登陆</h1>
<p>
<label for="email" class="uname" data-icon="u"> 电子邮件 </label>
<input id="email" name="email" required="required" type="email" placeholder="mymail@mail.com" >
</p>
<p>
<label for="password" class="youpasswd" data-icon="p"> 密码 </label>
<input id="password" name="password" required="required" type="password" placeholder="eg. 56482sjhjk" >
</p>
<p class="keeplogin">
<input type="checkbox" name="loginkeeping" id="loginkeeping" value="loginkeeping">
<label for="loginkeeping">记住我</label>
</p>
<p class="login button">
<input type="submit" value="登陆">
</p>
<p class="change_link">
还没有账号 ?
<a href="/#toregister" class="to_register">加入我们</a>
</p>
</form>
</div>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>IM 登陆</title>
<link rel="shortcut icon" href="static/image/favicon.ico">
<link rel="stylesheet" type="text/css" href="static/css/login/style3.css">
<link rel="stylesheet" type="text/css" href="static/css/login/animate-custom.css">
<link rel="stylesheet" href="static/layui/css/layui.css">
<script src="/static/layui/layui.js"></script>
<style type="text/css">
body {
background: url(static/image/4.jpg) no-repeat;
background-size: cover;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1 style="color:#F0F0F0">Scala 即时通讯系统</span></h1>
</header>
<section>
<div id="container_demo">
<a class="hiddenanchor" id="toregister"></a>
<a class="hiddenanchor" id="tologin"></a>
<div id="wrapper">
<div id="login" class="animate form">
<form action="" autocomplete="on" method="post" class="layui-form" lay-filter="login">
<h1>登陆</h1>
<p>
<label for="email" class="uname" data-icon="u"> 电子邮件 </label>
<input id="email" name="email" required="required" type="email"
placeholder="mymail@mail.com">
</p>
<p>
<label for="password" class="youpasswd" data-icon="p"> 密码 </label>
<input id="password" name="password" required="required" type="password"
placeholder="eg. 56482sjhjk">
</p>
<p class="keeplogin">
<input type="checkbox" name="loginkeeping" id="loginkeeping" value="loginkeeping">
<label for="loginkeeping">记住我</label>
</p>
<p class="login button">
<input type="submit" value="登陆">
</p>
<p class="change_link">
还没有账号 ?
<a href="/#toregister" class="to_register">加入我们</a>
</p>
</form>
</div>
<div id="register" class="animate form">
<form action="#" autocomplete="on" class="layui-form" lay-filter="register">
<h1> 注册 </h1>
<p>
<label for="usernamesignup" class="uname" data-icon="u">用户名</label>
<input id="usernamesignup" name="usernamesignup" required="required" type="text"
placeholder="myusername5500">
</p>
<p>
<label for="emailsignup" class="youmail" data-icon="e"> 电子邮件</label>
<input id="emailsignup" name="emailsignup" required="required" type="email"
placeholder="mymail@mail.com">
</p>
<p>
<label for="passwordsignup" class="youpasswd" data-icon="p">密码 </label>
<input id="passwordsignup" name="passwordsignup" required="required" type="password"
placeholder="eg. 56482sjhjk">
</p>
<p>
<label for="passwordsignup_confirm" class="youpasswd" data-icon="p">确认密码 </label>
<input id="passwordsignup_confirm" name="passwordsignup_confirm" required="required"
type="password" placeholder="eg. 56482sjhjk">
</p>
<p class="signin button">
<input type="submit" value="注册">
</p>
<p class="change_link">
已经有账号 ?
<a href="/#tologin" class="to_register"> 返回登陆 </a>
</p>
</form>
</div>
<div id="register" class="animate form">
<form action="#" autocomplete="on" class="layui-form" lay-filter="register">
<h1> 注册 </h1>
<p>
<label for="usernamesignup" class="uname" data-icon="u">用户名</label>
<input id="usernamesignup" name="usernamesignup" required="required" type="text" placeholder="myusername5500">
</p>
<p>
<label for="emailsignup" class="youmail" data-icon="e"> 电子邮件</label>
<input id="emailsignup" name="emailsignup" required="required" type="email" placeholder="mymail@mail.com">
</p>
<p>
<label for="passwordsignup" class="youpasswd" data-icon="p">密码 </label>
<input id="passwordsignup" name="passwordsignup" required="required" type="password" placeholder="eg. 56482sjhjk">
</p>
<p>
<label for="passwordsignup_confirm" class="youpasswd" data-icon="p">确认密码 </label>
<input id="passwordsignup_confirm" name="passwordsignup_confirm" required="required" type="password" placeholder="eg. 56482sjhjk">
</p>
<p class="signin button">
<input type="submit" value="注册">
</p>
<p class="change_link">
已经有账号 ?
<a href="/#tologin" class="to_register"> 返回登陆 </a>
</p>
</form>
</div>
</div>
</div>
</section>
</div>
</div>
</section>
</div>
<script src="/static/js/jquery-3.4.1.min.js" type="text/javascript"></script>
<script src="/static/js/cookie.js" type="text/javascript"></script>
<script src="/static/js/base64.js" type="text/javascript"></script>
<script type="text/javascript">
layui.use(['layer', 'form', 'jquery'], function(){
//layui组件
var layer = layui.layer, form = layui.form(), $ = layui.jquery;
//判断用户是否是从激活链接过来的
if (location.href.split("?").length == 2){
var status = location.href.split("?")[1].split("=")[1];
if (status == 1){
layer.msg("激活成功,请登录!");
}else{
layer.msg("激活失败,请重新激活!");
}
}
//监测邮件
$("#emailsignup").blur(function() {
$.ajax({
url:"user/existEmail",
type:"POST",
dataType:"JSON",
data:{email:$("#emailsignup").val()},
success:function(data) {
if(data.data){
$("#emailsignup").val("").focus();
layer.msg("此邮件已经被人注册过!");
}
},
error:function(data) {
layer.msg("服务器错误,请稍后再试!");
}
});
});
layui.use(['layer', 'form', 'jquery'], function () {
//layui组件
var layer = layui.layer, form = layui.form(), $ = layui.jquery;
//判断用户是否是从激活链接过来的
if (location.href.split("?").length == 2) {
var status = location.href.split("?")[1].split("=")[1];
if (status == 1) {
layer.msg("激活成功,请登录!");
} else {
layer.msg("激活失败,请重新激活!");
}
}
//编写函数,在按键升起时触发,监测cookie中是否存在该用户名的key,如果有,则把value赋值给密码框
$("#email").keyup(function () {
var email = $("#email").val();
if (email !== "") {
var mima = $.cookie($.base64.encode(email).replace("=",""));
if (mima != null) {
var mima = $.base64.decode(mima+"=")
$("#password").val(mima);
$("#loginkeeping").attr("checked", true);
console.log(email)
console.log(mima)
}
}
})
//监测邮件
$("#emailsignup").blur(function () {
$.ajax({
url: "user/existEmail",
type: "POST",
dataType: "JSON",
data: {email: $("#emailsignup").val()},
success: function (data) {
if (data.data) {
$("#emailsignup").val("").focus();
layer.msg("此邮件已经被人注册过!");
}
},
error: function (data) {
layer.msg("服务器错误,请稍后再试!");
}
});
});
//监测登录密码长度
$("#password").blur(function() {
$("#password").blur(function () {
var password = $("#password").val().trim();
if (!/^[\S]{6,12}$/.test(password)) {
layer.tips('密码必须6到12位', '#password');
$("#password").val("");
return ;
return;
}
});
//监测注册密码长度
$("#passwordsignup").blur(function() {
$("#passwordsignup").blur(function () {
var passwordsignup = $("#passwordsignup").val();
if (!/^[\S]{6,12}$/.test(passwordsignup)) {
layer.tips('密码必须6到12位', '#passwordsignup');
......@@ -138,84 +164,77 @@
$("#passwordsignup_confirm").blur(function () {
var passwordsignup_confirm = $("#passwordsignup_confirm").val();
var passwordsignup = $("#passwordsignup").val();
if (passwordsignup!='' && passwordsignup_confirm!='' && passwordsignup_confirm!=passwordsignup) {
if (passwordsignup != '' && passwordsignup_confirm != '' && passwordsignup_confirm != passwordsignup) {
layer.tips('两次密码不一致', '#passwordsignup_confirm');
$("#passwordsignup_confirm").val("");
$("#passwordsignup").val("");
}
})
//注册
form.on('submit(register)', function (data){
// var passwordsignup_confirm = $("#passwordsignup_confirm").val();
// var passwordsignup = $("#passwordsignup").val();
// if (passwordsignup != passwordsignup_confirm) {
// layer.tips('两次密码不一致', '#passwordsignup_confirm');
// $("#passwordsignup_confirm").val("");
// $("#passwordsignup").val("");
// return false;
// }
var d = {
'username':$("#usernamesignup").val(),
'email':$("#emailsignup").val(),
'password':$("#passwordsignup").val()
};
//loading层
var index = layer.load(0, {
shade: [0.6,'#fff'] //0.1透明度的白色背景
});
$.ajax({
url:"user/register",
dataType:"JSON",
contentType:"application/json",
type:"POST",
data:JSON.stringify(d),
success:function(data) {
layer.close(index);
layer.msg(data.msg + ",请先激活再登陆!");
window.location.href = "/#tologin";
},
error:function(data) {
layer.msg("服务器错误,请稍后再试!");
}
});
return false;
});
//登陆
form.on('submit(login)', function (data){
//注册
form.on('submit(register)', function (data) {
var d = {
'username': $("#usernamesignup").val(),
'email': $("#emailsignup").val(),
'password': $("#passwordsignup").val()
};
//loading层
var index = layer.load(0, {
shade: [0.6, '#fff'] //0.1透明度的白色背景
});
$.ajax({
url: "user/register",
dataType: "JSON",
contentType: "application/json",
type: "POST",
data: JSON.stringify(d),
success: function (data) {
layer.close(index);
layer.msg(data.msg + ",请先激活再登陆!");
window.location.href = "/#tologin";
},
error: function (data) {
layer.msg("服务器错误,请稍后再试!");
}
});
return false;
});
//登陆
form.on('submit(login)', function (data) {
var check = document.getElementById("loginkeeping").checked;
var d = {'email': $("#email").val(),'password': $("#password").val()};
//loading层
var index = layer.load(1, {
shade: [0.6,'#fff'] //0.1透明度的白色背景
});
$.ajax({
url:"user/login?check="+check,
dataType:"JSON",
contentType:"application/json",
type:"POST",
data:JSON.stringify(d),
success:function(data) {
layer.close(index);
if (data.code == 1) {
layer.msg(data.msg);
$("#password").val("");
} else if(data.code == 0) {
var host = window.location.host;
if(window.location.port != "") {
host = host + ":" + window.location.host;
}
window.location.href = "http://" + host + "/user/index";
}
},
error:function(data) {
layer.msg("服务器错误,请稍后再试!");
}
});
return false;
});
});
var d = {'email': $("#email").val(), 'password': $("#password").val()};
//loading层
var index = layer.load(1, {
shade: [0.6, '#fff'] //0.1透明度的白色背景
});
$.ajax({
url: "user/login?check=" + check,
dataType: "JSON",
contentType: "application/json",
type: "POST",
data: JSON.stringify(d),
success: function (data) {
layer.close(index);
if (data.code == 1) {
layer.msg(data.msg);
$("#password").val("");
} else if (data.code == 0) {
var host = window.location.host;
if (window.location.port != "") {
host = host + ":" + window.location.host;
}
window.location.href = "http://" + host + "/user/index";
}
},
error: function (data) {
layer.msg("服务器错误,请稍后再试!");
}
});
return false;
});
})
;
</script>
</body>
</html>
\ No newline at end of file
/*!
* jquery.base64.js 0.1 - https://github.com/yckart/jquery.base64.js
* Makes Base64 en & -decoding simpler as it is.
*
* Based upon: https://gist.github.com/Yaffle/1284012
*
* Copyright (c) 2012 Yannick Albert (http://yckart.com)
* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php).
* 2013/02/10
**/
;(function($) {
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
a256 = '',
r64 = [256],
r256 = [256],
i = 0;
var UTF8 = {
/**
* Encode multi-byte Unicode string into utf-8 multiple single-byte characters
* (BMP / basic multilingual plane only)
*
* Chars in range U+0080 - U+07FF are encoded in 2 chars, U+0800 - U+FFFF in 3 chars
*
* @param {String} strUni Unicode string to be encoded as UTF-8
* @returns {String} encoded string
*/
encode: function(strUni) {
// use regular expressions & String.replace callback function for better efficiency
// than procedural approaches
var strUtf = strUni.replace(/[\u0080-\u07ff]/g, // U+0080 - U+07FF => 2 bytes 110yyyyy, 10zzzzzz
function(c) {
var cc = c.charCodeAt(0);
return String.fromCharCode(0xc0 | cc >> 6, 0x80 | cc & 0x3f);
})
.replace(/[\u0800-\uffff]/g, // U+0800 - U+FFFF => 3 bytes 1110xxxx, 10yyyyyy, 10zzzzzz
function(c) {
var cc = c.charCodeAt(0);
return String.fromCharCode(0xe0 | cc >> 12, 0x80 | cc >> 6 & 0x3F, 0x80 | cc & 0x3f);
});
return strUtf;
},
/**
* Decode utf-8 encoded string back into multi-byte Unicode characters
*
* @param {String} strUtf UTF-8 string to be decoded back to Unicode
* @returns {String} decoded string
*/
decode: function(strUtf) {
// note: decode 3-byte chars first as decoded 2-byte strings could appear to be 3-byte char!
var strUni = strUtf.replace(/[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars
function(c) { // (note parentheses for precence)
var cc = ((c.charCodeAt(0) & 0x0f) << 12) | ((c.charCodeAt(1) & 0x3f) << 6) | (c.charCodeAt(2) & 0x3f);
return String.fromCharCode(cc);
})
.replace(/[\u00c0-\u00df][\u0080-\u00bf]/g, // 2-byte chars
function(c) { // (note parentheses for precence)
var cc = (c.charCodeAt(0) & 0x1f) << 6 | c.charCodeAt(1) & 0x3f;
return String.fromCharCode(cc);
});
return strUni;
}
};
while(i < 256) {
var c = String.fromCharCode(i);
a256 += c;
r256[i] = i;
r64[i] = b64.indexOf(c);
++i;
}
function code(s, discard, alpha, beta, w1, w2) {
s = String(s);
var buffer = 0,
i = 0,
length = s.length,
result = '',
bitsInBuffer = 0;
while(i < length) {
var c = s.charCodeAt(i);
c = c < 256 ? alpha[c] : -1;
buffer = (buffer << w1) + c;
bitsInBuffer += w1;
while(bitsInBuffer >= w2) {
bitsInBuffer -= w2;
var tmp = buffer >> bitsInBuffer;
result += beta.charAt(tmp);
buffer ^= tmp << bitsInBuffer;
}
++i;
}
if(!discard && bitsInBuffer > 0) result += beta.charAt(buffer << (w2 - bitsInBuffer));
return result;
}
var Plugin = $.base64 = function(dir, input, encode) {
return input ? Plugin[dir](input, encode) : dir ? null : this;
};
Plugin.btoa = Plugin.encode = function(plain, utf8encode) {
plain = Plugin.raw === false || Plugin.utf8encode || utf8encode ? UTF8.encode(plain) : plain;
plain = code(plain, false, r256, b64, 8, 6);
return plain + '===='.slice((plain.length % 4) || 4);
};
Plugin.atob = Plugin.decode = function(coded, utf8decode) {
coded = String(coded).split('=');
var i = coded.length;
do {--i;
coded[i] = code(coded[i], true, r64, a256, 6, 8);
} while (i > 0);
coded = coded.join('');
return Plugin.raw === false || Plugin.utf8decode || utf8decode ? UTF8.decode(coded) : coded;
};
}(jQuery));
\ No newline at end of file
/*!
* jQuery Cookie Plugin v1.4.0
* https://github.com/carhartl/jquery-cookie
*
* Copyright 2013 Klaus Hartl
* Released under the MIT license
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as anonymous module.
define(['jquery'], factory);
} else {
// Browser globals.
factory(jQuery);
}
}(function ($) {
var pluses = /\+/g;
function encode(s) {
return config.raw ? s : encodeURIComponent(s);
}
function decode(s) {
return config.raw ? s : decodeURIComponent(s);
}
function stringifyCookieValue(value) {
return encode(config.json ? JSON.stringify(value) : String(value));
}
function parseCookieValue(s) {
if (s.indexOf('"') === 0) {
// This is a quoted cookie as according to RFC2068, unescape...
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
}
try {
// Replace server-side written pluses with spaces.
// If we can't decode the cookie, ignore it, it's unusable.
s = decodeURIComponent(s.replace(pluses, ' '));
} catch(e) {
return;
}
try {
// If we can't parse the cookie, ignore it, it's unusable.
return config.json ? JSON.parse(s) : s;
} catch(e) {}
}
function read(s, converter) {
var value = config.raw ? s : parseCookieValue(s);
return $.isFunction(converter) ? converter(value) : value;
}
var config = $.cookie = function (key, value, options) {
// Write
if (value !== undefined && !$.isFunction(value)) {
options = $.extend({}, config.defaults, options);
if (typeof options.expires === 'number') {
var days = options.expires, t = options.expires = new Date();
t.setDate(t.getDate() + days);
}
return (document.cookie = [
encode(key), '=', stringifyCookieValue(value),
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
options.path ? '; path=' + options.path : '',
options.domain ? '; domain=' + options.domain : '',
options.secure ? '; secure' : ''
].join(''));
}
// Read
var result = key ? undefined : {};
// To prevent the for loop in the first place assign an empty array
// in case there are no cookies at all. Also prevents odd result when
// calling $.cookie().
var cookies = document.cookie ? document.cookie.split('; ') : [];
for (var i = 0, l = cookies.length; i < l; i++) {
var parts = cookies[i].split('=');
var name = decode(parts.shift());
var cookie = parts.join('=');
if (key && key === name) {
// If second argument (value) is a function it's a converter...
result = read(cookie, value);
break;
}
// Prevent storing a cookie that we couldn't decode.
if (!key && (cookie = read(cookie)) !== undefined) {
result[name] = cookie;
}
}
return result;
};
config.defaults = {};
$.removeCookie = function (key, options) {
if ($.cookie(key) !== undefined) {
// Must not alter options, thus extending a fresh object...
$.cookie(key, '', $.extend({}, options, { expires: -1 }));
return true;
}
return false;
};
}));
\ No newline at end of file
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册