【JavaWeb】在线视频播放平台 登录校验 退出登录 Cookie Redis模拟Session 项目笔记讲解总结

总结登录的流程:

一、前端界面

cc-check.login.js

首先将登录校验封装起来,这其中涉及到后端的接口checkLogin():

//检查admin登录状态
//发送ajax请求到后端,查看redis是否存在
function checkLogin(callback){//callback到时候传入一个回调函数
    //实现检查登录的业务
    let tokenLayuimini = $.cookie("token-layuimini");
    if(tokenLayuimini){
        //token-layuimini 不为空 做判定 是否其value 在redis中存在
        $.ajax({
            type: 'post',
            url: 'http://localhost:8080/study/admin',
            data: {op: 'checkLogin', token: tokenLayuimini},
            async: false,//这里需要同步。
            dataType: 'json',
            success: function (r) {
                callback(r);
            }
        });
    }else{
        //没登陆
        callback({code: 500, msg: 'token-layuimini不存在,未登录状态',data: undefined});
    }
}

①index.html

这是系统的首页,上来就需要登录校验。

<!--    引入jQuery 、cookies插件 、以及check.login.js-->
    <script src="js/jquery-min-3.6.0.js"></script>
    <script src="../bilibili/js/jquery.cookie.js"></script>
<!--    引入admin的登录校验-->
    <script src="js/cc-check.login.js"></script>
    
    <script>
        $(document).ready(function(){
            //登录状态校验
            checkLogin(function(res){// 这里的res就是校验的结果
                if(res.code==200){
                    $("#current-login-admin-name").html("欢迎您!【"+ res.data.adminName +"】");
                    // alert("欢迎您["+res.data.adminName+"]!");
                }else{
                    location.href = "http://localhost:8080/study/layuimini/login-1.html";
                }
            });
            
            //for test
            // checkLogin();
        });
	
        //退出登录
        function doExit(){
            $.ajax({
                type:"get",
                url:"http://localhost:8080/study/admin",
                data:{op:"exit",token:$.cookie('token-layuimini')},
                success:function(){
                    $.cookie("token-layuimini", null, {path:"http://localhost:8080/study/layuimini"});
                    location.href="index.html";
                }
            })
        }
    </script>

注意事项:引入js的顺序不能乱

退出登录比较简单设置cookie为null,并且在redis中del(“tokenValue”)。

②login.html

二、后端接口

首先需要一个工具类:

RedisUtil:

用于创建Jedis连接池提高效率,对redis数据库中的数据进行操作。

package com.qidian.study.util;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.io.IOException;
import java.util.Map;
import java.util.Properties;

public class RedisUtil {
    private static String host = "127.0.0.1";
    private static String port = "6379";
    private static JedisPool pool;
    static {
        //自动加载resourses中文件配置
        Properties ps = new Properties();
        try {
            ps.load(RedisUtil.class.getClassLoader().getResourceAsStream("redis.properties"));
            host = ps.getProperty("redis.host");
            port = ps.getProperty("redis.port");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //获取可用链接的方法
    public synchronized static Jedis getJedis(){
        return new Jedis(host,new Integer(port));
    }
    public static String set(String key,String value){
        Jedis jedis = new Jedis();
        String result = jedis.set(key,value);
        jedis.close();
        return result;

    }
    public static String get(String key){
        Jedis jedis = getJedis();
        String result = getJedis().get(key);
        jedis.close();
        return result;
    }

    public static Long hset(String key,String field,String value){
        Jedis jedis = getJedis();
        Long result = getJedis().hset(key,field,value);
        jedis.close();
        return result;
    }
    public static String hmset(String key, Map map){
        Jedis jedis = getJedis();
        String result = getJedis().hmset(key,map);
        jedis.close();
        return result;
    }
    public static String hget(String key,String filed){
        Jedis jedis = getJedis();
        String result = getJedis().hget(key,filed);
        jedis.close();
        return result;
    }
    public static Map hgetAll(String key){
        Jedis jedis = getJedis();
        Map result = getJedis().hgetAll(key);
        jedis.close();
        return result;
    }

    public static Long expire(String key,int second){
        Jedis jedis = getJedis();
        Long result = getJedis().expire(key,second);
        jedis.close();
        return result;
    }

    public static Long persist(String key){
        Jedis jedis = getJedis();
        Long result = getJedis().persist(key);
        jedis.close();
        return result;
    }

    public static Long del(String key){
        Jedis jedis = getJedis();
        Long result =  getJedis().del(key);
        if(result == 1){
            System.out.println("用户退出登录成功");
        }
        jedis.close();
        return result;
    }

    public static boolean exists(String key){
        Jedis jedis = getJedis();
        boolean result = getJedis().exists(key);
        jedis.close();
        return result;
    }
}

①login()登录

servlet层:

//登陆业务
public void login(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException{
    //获取请求前端输入参数
    String adminName = request.getParameter("adminName");
    String adminPass = request.getParameter("adminPass");
    response.setContentType("application/json;charSet=utf-8");
    //调取service方法
    response.getWriter().write(JsonTools.object2json(adminService.login(adminName, adminPass)));
}

service层:

@Override
public VideoResponse login(String adminName, String adminPass) {
    Admin adminbase = adminDAO.queryByName(adminName);
    if(adminbase == null){
        return VideoResponse.error(500,"登陆失败");
    }else {
        if(!adminbase.getAdminPass().equals(adminPass)){
            return VideoResponse.error(500,"登陆失败");
        }else {

            //将用户信息放入redis
            //生成一个token
            String token = UUID.randomUUID().toString().replace("-","")+(new Random().nextInt(900)+100);
            adminbase.setAdminPass("");
            redisUtil.hset(token,"admin",JsonTools.object2json(adminbase));//存入redis中
            String adminJson = JsonTools.object2json(adminbase);
            //设置存活时间30min
            redisUtil.expire(token,60*30);
            //响应servlet
            return VideoResponse.ok(token,adminbase);//把用户信息,跟用户生成的token一起返回
        }
    }
}

dao层需要一个queryByName()以校验密码是否正确:

@Override
public Admin queryByName(String adminName) {
    Admin admin = null;
    String sql = "select * from v_admin where admin_name = ?";
    try {
        con = getCon();
        pst = con.prepareStatement(sql);
        pst.setString(1, adminName);
        rs = pst.executeQuery();
        if (rs.next()) {
            admin = new Admin();
            admin.setAdminId(rs.getLong("admin_id"));
            admin.setAdminName(rs.getString("admin_name"));
            admin.setAdminPass(rs.getString("admin_pass"));
            admin.setAdminRole(rs.getInt("admin_role"));
            admin.setCreateTime(rs.getString("create_time"));
            admin.setModifyTime(rs.getString("modify_time"));
            admin.setStatus(rs.getInt("status"));
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        closeAll(rs, pst, con);
    }
    return admin;
}

②exit()退出登录

servlet层

public void exit(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException{
    //获取请求前端输入参数
    String token = request.getParameter("token");
    response.setContentType("application/json;charSet=utf-8");
    //调取service方法
    response.getWriter().write(JsonTools.object2json(adminService.exit(token)));
}

service层:

@Override
public VideoResponse exit(String token) {
    //从redis中删除对应token
    if(redisUtil.del(token) == 1){
        System.out.println("删除token-layuimini成功");
    }
    return VideoResponse.ok();
}

没有dao层。

③checkLogin

servlet层

public void checkLogin(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException{
    //获取请求前端输入参数
    String token = request.getParameter("token");
    response.setContentType("application/json;charSet=utf-8");
    //调取service方法
    response.getWriter().write(JsonTools.object2json(adminService.checkLogin(token)));
}

service层:

@Override
public VideoResponse checkLogin(String token) {
    if(token == null){
        return VideoResponse.error();
    }
    if(redisUtil.exists(token)){
        //存在
        //刷新存活时间30min
        redisUtil.expire(token,60*30);
        //取用户对象
        String adminJson = redisUtil.hget(token,"admin");
        //将json转换为admin对象
        Admin adminbase = JsonTools.json2object(adminJson,Admin.class);
        return VideoResponse.ok(token,adminbase);
    }
    return VideoResponse.error();
}

没有dao层。

GetRedisInfoServlet:

在渲染个人视频列表时需要用到这个servlet,因为我们登录的时候把个人信息都放进去了,而在渲染个人视频列表时需要知道当前登录的人的userId。

@WebServlet("/redis")
public class GetRedisInfoServlet extends BaseServlet{
    //注意这个方法为了方便没有设置业务层以及DAO层
        //通过token 获取redis中存储的user信息
    //这个用于获取当前登录的用户信息
    //使用的地方:个人视频列表personal-videos.html
    public void getRedisInfo (HttpServletRequest req, HttpServletResponse resp) 
        throws IOException, ServletException {
            String token = req.getParameter("token");
            String userInfo = RedisUtil.hget(token, "user");
            resp.setContentType("application/json; charset=utf-8");
            resp.getWriter().write(userInfo);
    }
    //for test
    //http://localhost:8080/study/redis?op=getRedisInfo&token=带上token
}

三、总结

登录的过程

​ 前台获取username和userpass,后端校验。失败返回error();成功就生成一个uuid+随机数作为token的value,并且获取这个登陆成功的这个用户的信息(将密码设空),然后调用RedisUtil工具类操作redis数据库,将uuid+随机数作为key,将“admin”作为field,将这个用户信息(转成json字符串)作为value,设置好存活时间,放入redis数据库中,然后响应前端ok(200, “uuid+随机数”, 用户信息),返回用户信息给前端的原因我也不知道,因为没用到这个返回的用户信息,现在看来是可以不返回的,因为我写了GetRedisInfoServlet可以获取key field对应的value,也就是当前登录的用户信息。

​ 前端根据状态码(200/500)判断登录成功与否,如果失败,alert登陆失败。如果成功,利用$.cookie()生成一个cookie,设置好name,value,expires,path,然后就可以跳转至index.html了。

退出登录的过程

​ 如果token不为null的话,前端发送一个$.ajax请求到后端,带上token的value,后端调用RedisUtil操作redis数据库,执行删除del(“tokenValue”),根据这个函数返回值判断是否删除成功(如果成功删除1个key的话在Jedis中返回的是Long类型的1),响应前端。

​ 前端判断是否删除成功,如果删除成功,将cookie中对应的token的value设为null。这样就完成了退出登录的操作。

登录校验的过程

​ 在需要登录校验的地方,首先获取并判断对应token是否为null,为null把相应的欢迎词修改为注册 | 登录,或者也可以直接跳转至登录界面;不为空就发送一个$.ajax请求,带上对应的token的value,后端调用redisUtil.exists(token)判断redis中是否存在这个key,如果存在就刷新redis数据库中这条记录的存活时间(因为需要用户操作一下就刷新存活时间),老师在这边返回了当前登录的用户的信息,这里倒是需要的,因为首次登录要把对应的登录 | 注册改为欢迎您!【userName】,这里需要用户信息中的userName。

GetRedisInfoServlet的作用:

​ 用于获取当前登录的用户的用户信息,这个信息是我们成功登录后放在redis中的,需要通过uuid+随机数(也就是客户端cookie中token对应的value)获取,老师在成功登录后也将这个用户信息返回给了前端,我目前没有用到,而在渲染个人视频列表的时候,需要知道当前登录的用户信息的userId,因此我写了这个servlet,现在想来,也可以直接再登录校验一次,也能获取到当前登录的用户信息,不用多写一个servlet了,大家可以试试。

后期上传《在线视频播放平台》项目源码。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_小鹰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值