发表于: 2019-12-27 22:38:43
1 1050
今天做了什么
学习cookie,session,token
简单学习加密的使用,md5加密,des加密
des加密工具类
ublic class DesUtil {
private static String keyData = "ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstwxyz0123456789-_.";
//安全密钥
public DesUtil() {
}
//无参构造
public DesUtil(String key) {
keyData = key;
}
//有参构造
/**
* 将Long类型加密
*
* @param source
* @return
* @throws UnsupportedEncodingException
*/
public static String encryptFromLong(long source) throws UnsupportedEncodingException {
String source1 = String.valueOf(source);
//先将long类型转化为String类型
return encrypt(source1, "UTF-8");
}
/**
* 将解密好的转化为long类型
*
* @param encryptedData
* @return
* @throws UnsupportedEncodingException
*/
public static long decryptToLong(String encryptedData) {
long decryptLong = 0;
try {
decryptLong = Long.valueOf(decrypt(encryptedData, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return decryptLong;
}
/**
* 加密UTF-8,调用底下的方法
*
* @param source 待加密数据
* @return 加密完成的数据
* @throws UnsupportedEncodingException 异常
*/
public static String encrypt(String source) throws UnsupportedEncodingException {
return encrypt(source, "UTF-8");
}
/**
* 解密UTF-8,调用底下的方法
*
* @param encryptedData 待解密数据
* @return 解密完成数据
* @throws UnsupportedEncodingException 异常
*/
public static String decrypt(String encryptedData) {
String miwen = null;
try {
miwen = decrypt(encryptedData, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return miwen;
}
/**
* 功能:加密
*
* @param source 待加密数据
* @param charSet 字符编码
* @return 加密完成数据
* @throws UnsupportedEncodingException 异常
*/
public static String encrypt(String source, String charSet)
throws UnsupportedEncodingException {
String encrypt = null;
byte[] ret = encrypt(source.getBytes(charSet));
encrypt = new String(Base64.encode(ret));
return encrypt;
}
/**
* 功能:解密
*
* @param encryptedData 待解密数据
* @param charSet 字符编码
* @return 解密完成数据
* @throws UnsupportedEncodingException 异常
*/
public static String decrypt(String encryptedData, String charSet)
throws UnsupportedEncodingException {
String decryptedData = null;
byte[] ret = decrypt(Base64.decode(String.valueOf(encryptedData.toCharArray())));
decryptedData = new String(ret, charSet);
return decryptedData;
}
/**
* 加密
*
* @param primaryData
* @return
*/
private static byte[] encrypt(byte[] primaryData) {
//取得安全密钥
byte[] rawKeyData = getKey();
//DES算法要求有一个可信任的随机数源
SecureRandom sr = new SecureRandom();
//使用原始密钥数据创建DESKeySpec对象
DESKeySpec dks = null;
try {
dks = new DESKeySpec(keyData.getBytes());
} catch (InvalidKeyException e) {
e.printStackTrace();
}
//创建一个密钥工厂
SecretKeyFactory keyFactory = null;
try {
keyFactory = SecretKeyFactory.getInstance("DES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
//用密钥工厂把DESKeySpec转换成一个SecretKey对象
SecretKey key = null;
try {
key = keyFactory.generateSecret(dks);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
// Cipher对象实际完成加密操作
Cipher cipher = null;
try {
cipher = Cipher.getInstance("DES");
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
e.printStackTrace();
}
// 用密钥初始化Cipher对象
try {
cipher.init(Cipher.ENCRYPT_MODE, key, sr);
} catch (InvalidKeyException e) {
e.printStackTrace();
}
// 正式执行加密操作
byte encryptedData[] = null;
try {
encryptedData = cipher.doFinal(primaryData);
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
}
//返回加密数据
return encryptedData;
}
/**
* 加密
*
* @param encryptedData
* @return
*/
private static byte[] decrypt(byte[] encryptedData) {
/** DES算法要求有一个可信任的随机数源 */
SecureRandom sr = new SecureRandom();
/** 取得安全密钥 */
byte rawKeyData[] = getKey();
/** 使用原始密钥数据创建DESKeySpec对象 */
DESKeySpec dks = null;
try {
dks = new DESKeySpec(keyData.getBytes());
} catch (InvalidKeyException e) {
e.printStackTrace();
}
/** 创建一个密钥工厂 */
SecretKeyFactory keyFactory = null;
try {
keyFactory = SecretKeyFactory.getInstance("DES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
/** 用密钥工厂把DESKeySpec转换成一个SecretKey对象 */
SecretKey key = null;
try {
key = keyFactory.generateSecret(dks);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
/** Cipher对象实际完成加密操作 */
Cipher cipher = null;
try {
cipher = Cipher.getInstance("DES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
/** 用密钥初始化Cipher对象 */
try {
cipher.init(Cipher.DECRYPT_MODE, key, sr);
} catch (InvalidKeyException e) {
e.printStackTrace();
}
/** 正式执行解密操作 */
byte decryptedData[] = null;
try {
decryptedData = cipher.doFinal(encryptedData);
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return decryptedData;
}
/**
* 获得密钥
*
* @return
*/
private static byte[] getKey() {
/** DES算法要求有一个可信任的随机数源 */
SecureRandom sr = new SecureRandom();
/** 为我们选择的DES算法生成一个密钥生成器对象 */
KeyGenerator kg = null;
try {
kg = KeyGenerator.getInstance("DES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
kg.init(sr);
/** 生成密钥工具类 */
SecretKey key = kg.generateKey();
/** 生成密钥byte数组 */
byte rawKeyData[] = key.getEncoded();
return rawKeyData;
}
}
对密码进行md5加密(直接调用spring的md5工具类进行加密)
//对密码进行md5加密
String md5Password = DigestUtils.md5DigestAsHex(password.getBytes());
登录的具体逻辑,成功校验用户和密码后返回一个cookie,把生成的token放入cookie中返回给客户端
使用postman测试
cookie,session,token总结:
会话:
这里的会话指的是web开发中的一次通话过程,当打开浏览器,访问网站地址后,会话开始,当关闭浏览器(或者到了过期时间),会话结束。
会话管理技术:
共享同一个客户浏览器多个请求中数据,例如购物车。登录权限(简单权限过滤)
cookie:
(1)什么是cookie?
它是客户端浏览器的缓存文件,里面记录了客户端浏览器访问网站的一些内容。它也是Http协议请求和响应消息头的一部分。
(2)cookie能做什么?
能保存客户端浏览器访问网站的相关内容,需要服务器开启cookie。从而每一次访问时,先从本地获取缓存,使用资源共享,并且提高效率。
(3)Cookie的说明。
Cookie有大小,个数限制。每个网站最多只能存20个cookie,且大小不能超过4kb。(32bit 不能超过4096MB)同时,所有网站的cookie总数不超过300个。
(4)Cookie中的属性
属性:
name:必要属性,cookie的名称。
value:必要属性,cookie的值(不能是中文)
---------------------------可选属性---------------------------------
path:cookie的路径(重要)
domain:cookie的域名(重要),相当于访问的网站(localhost)
maxAge:cookie的生存时间(相当于生命周期的活着)(比较重要),
当删除cookie时,设置该值为0。
当不设置该值时,使用的是浏览器的内存,当关闭浏览器之后,cookie将丢失。设置了此值,就会保存成缓存文件(值必须是大于0的,以秒为单位)。
version:cookie的版本号。(不重要)
comment:cookie的说明。(不重要)
(5) 在web应用中如何设置和获取Cookie
定义一个Cookie
Cookie cookie = new Cookie(cookieName,cookieValue);
HttpServletRequest 获取 Cookie
Cookie[] cookies = request.getCookies();
该方法返回的是一个数组。(为什么是数组呢,方便,可以直接拿到与该请求相关的所有cookie)
HttpServletResponse 添加Cookie
response.addCookie(cookie);
添加一个cookie,其实就是添加一个响应消息头
response.setHeader("Set-Cookie","name=value;path=;maxage=;domain=");
(为什么没有set方法,原因是set就会把之前的覆盖,所以每次都是添加)。
如何确定一个唯一的cookie:cookieName+cookiePath+cookieDomain
定位一个cookie是由 cookie的名称和路径,主机(访问的资源)三部分组成
session:
(1)什么是Session?
它是一个服务端会话对象,存储用户的会话数据。
(2)获取session的两种方式
方式一:request:getSession();
1)查看是否有jsessionid;
1)有通过jsessionid获取session;
2)有这块区域就直接用了。
2)没有这块区域就开辟一块session区域。
1)没有直接开辟一块session的区域。
方式二:request:getSession(Boolean b);
若结果为rue和上面的方法一样,下面是false的解释。
查看是否有jsessionid;
1)有通过jsessionid获取session;
2)有这块区域就直接用了。
2) 没有直接返回null
(3)HttpSession对象的状态
a、什么是持久态
把长时间不用,但还不到过期时间的HttpSession进行序列化,写到磁盘上。
我们把HttpSession持久态也叫做钝化。(与钝化相反的,我们叫活化。)
b、什么时候使用持久化
第一种情况:当访问量很大时,服务器会根据getLastAccessTime来进行排序,对长时间不用,但是还没到过期时间的HttpSession进行持久化。
第二种情况:当服务器进行重启的时候,为了保持客户HttpSession中的数据,也要对HttpSession进行持久化。
5、关于jsessionid说明
当我们在JAVA后台获取到一块session空间的时候,返回时已经将这块session的id也就是jsessionid代入到浏览器的cookie中(前提是cookie打开),如果你的浏览器cookie没有打开,
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//将字符集设置,放在方法体首位
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("text/html;UTF-8");
HttpSession session = request.getSession();
System.out.println(session);
String reUrl =
response.encodeRedirectURL("TestServlet");//浏览器cookie没有打开只用这个方法,可以在url后面加上jsessionid,保持会话的持续,注意的是需要所有的跳转都加上这个方法才可以保持jsessionid的拼接
response.sendRedirect(reUrl);
}
例如:http://localhost:8080/ssm/TestServlet;jsessionid=059A89AE1D32790B3DB6C61C5E138DD1
带jsessionid的url到后台后,可直接获取session,如果存在获取到的session对象是和之前一样的对象。
token:
参考:https://mp.weixin.qq.com/s/DkwfpZibKdllfm0lpxukWg
https://www.cnblogs.com/JamesWang1993/p/8593494.html
Token的引入:Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token便应运而生。
Token的定义:Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。最简单的token组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,由token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接token请求服务器)。
使用Token的目的:Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。
Token 能解决哪些问题呢?有如下几点:
Token 完全由应用管理,所以它可以避开同源策略。
Token 可以避免 CSRF 攻击(http://dwz.cn/7joLzx)。
Token 可以是无状态的,可以在多个服务间共享。
遇到的问题:
对于md5和des加密细节不了解
明天要做什么:
添加拦截器,使只有登录的用户才能查看职业页面
添加注销功能
评论