JavaWeb——后端之登录功能

news2024/11/17 9:59:49

6. 登录功能

6.1 登录认证

只进行用户名和密码是否存在的操作

@Slf4j
@RestController
public class LoginController {
    @Autowired
    public EmpService empService;

    @PostMapping("/login")
    public Result login(@RequestBody Emp emp) {
        log.info("{}员工登录", emp);
        Emp e = empService.login(emp);
        return e != null? Result.success(): Result.error("用户名或密码错误");
    }
}

Emp login(Emp emp);

@Override
public Emp login(Emp emp) {
    Emp e = empMapper.getByUsernameAndPassword(emp);
    return e;
}

@Select("select * from emp where username = #{username} and password = #{password}")
Emp getByUsernameAndPassword(Emp emp);

问题:在未登录的情况下,也可以直接访问部门管理、员工管理等功能

6.2 登录校验

请求来的时候线进行登录校验,校验通过的话,执行业务;不通过就跳转到登录界面

在这里插入图片描述

1)会话技术

会话: 浏览器和服务器ide一次连接,一次会话中可以包含多次请求和响应

会话跟踪: 服务器需要识别多次请求是否来自同一浏览器,以便在同一次会话的多次请求间共享数据

会话跟踪方案:

  • 客户端会话跟踪技术:Cookie
  • 服务端会话跟踪技术:Session
  • 令牌技术

Cookie:

①特点

  • 浏览器第一次发送请求给服务器的时候,服务器自动将Cookie返回给浏览器
  • 浏览器自动将收到的Cookie存储在本地
  • 浏览器向服务器发送请求的时候,自动携带Cookie

②优点

HTTP协议中支持的技术,浏览器自动进行

在这里插入图片描述

③缺点

  • 移动端APP无法使用Cookie
  • 不安全,用户可以自己禁用Cookie(在浏览器的设置里面)
  • Cookie不能跨域(协议、IP/域名、端口)

Session:

①特点

  • 基于Cookie

②优点

  • 存储在服务器端,安全

    在这里插入图片描述

③缺点

  • 服务器集群环境下无法直接使用Session
  • Cookie的缺点

令牌技术:

①特点

字符串的形式,可以存储在任何容器中,不只是可以存储在Cookie中

②优点

  • 支持PC端、移动端
  • 解决集群环境下的认证问题
  • 减轻服务器端存储压力

在这里插入图片描述

③缺点

  • 需要自己实现

2)JWT令牌

全称:JSON Web Token(https://jwt.io/)

定义了一种**简洁(就是字符串)**的、**自包含(可以在其中包括用户名等需要的字符串)**的格式,用于在通信双方以json数据格式安全地传输信息。由于数字签名的存在,这些信息是可靠的

组成:

第一部分:Header(头),记录令牌类型、签名算法等;采用Base64编码

第二部分:Payload(有效荷载),携带一些自定义信息、默认信息等;采用Base64编码

第三部分:Signature(签名),防止Token被篡改、确保安全性。将header、payload融入,并加入指定密钥,通过指定前面算法计算而来

例:

在这里插入图片描述

案例:

添加依赖

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
    // 生成JWTT
    @Test
    public void testGenJwt() {
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", 1);
        claims.put("name", "tom");

        String jwt = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, "itheima")  // 签名算法和密钥
                .setClaims(claims)  // 自定义内容
                .setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000))  // 设置有效期为1h
                .compact();
        System.out.println(jwt);
    }

    // 解析JWT
    @Test
    public void testParseJwt() {
        Claims claims = Jwts.parser()
                .setSigningKey("itheima")  // 密钥
                .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoidG9tIiwiaWQiOjEsImV4cCI6MTcwNDY5Njg1NH0.MzTlN_jrVSa7UJtTFoXw4xQ9-t4R7JHUmHeom5KQ2ss")
                .getBody();
        System.out.println(claims);
    }

错误

java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter

解决:

引入依赖

        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>

登录-生成令牌

@Slf4j
@RestController
public class LoginController {
    @Autowired
    public EmpService empService;

    @PostMapping("/login")
    public Result login(@RequestBody Emp emp) {
        log.info("{}员工登录", emp);
        Emp e = empService.login(emp);
        // 登录成功,生成令牌,下发令牌
        if (e != null) {
            Map<String, Object> claims = new HashMap<>();
            claims.put("id", e.getId());
            claims.put("name", e.getName());
            claims.put("username", e.getUsername());
            String jwt = JwtUtils.generateJwt(claims);  // jwt包含了当前登录的员工信息
            return Result.success(jwt);
        }
        // 登录失败,返回错误信息
        return Result.error("用户名或密码错误");
    }
}

3)过滤器Filter

概念: 过滤器是JavaWeb三大组件(Servlet、Filter、Listener)之一

功能: 把对资源的请求拦截下来,从而实现一些特殊功能,例如:登录校验、统一编码处理、敏感字符处理等

实现:

  • 实现Filter接口
  • @WebFilter(urlPatterns=“/*”)
  • @ServletComponentScan——让启动类知道
@WebFilter(urlPatterns = "/*")  // 拦截所有请求
public class DemoFilter implements Filter {

    @Override  // 初始化方法,只调用一次
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init初始化方法执行了");
    }

    @Override  // 拦截到请求之后调用
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("拦截到了请求");
        // 放行
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override  // 销毁方法,只调用一次
    public void destroy() {
        System.out.println("destroy销毁方法执行了");
    }
}

执行流程:

在这里插入图片描述

拦截路径:

在这里插入图片描述

过滤器链:

一个web应用有中,可以配置多个过滤器,多个过滤器就形成了一个过滤器链

顺序——注解配置的Filter,优先级是按照过滤器类名(字符串)的自然排序

在这里插入图片描述

@Slf4j
@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // Tomcat传入的是request实际上是HTTPrequest,要进行强制类型转换
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        // 1. 获取请求url
        String url = req.getRequestURL().toString();
        log.info("请求的url:{}", url);

        // 2. 判断请求url中是否包含login,如果包含,说明是登录操作,放行
        if (url.contains("login")) {
            log.info("放行");
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        // 3. 获取请求头中的令牌(token)
        String jwt = req.getHeader("token");
        // 4. 判断令牌是否存在,如果不存在,返回错误结果(未登录)
        if (!StringUtils.hasLength(jwt)) {
            log.info("请求头token为空,返回未登录的信息");
            Result erro = Result.error("NOT_LOGIN");
            // 手动将Result对象转化为json格式——alibaba,fastJSON
            String notLogin = JSONObject.toJSONString(erro);
            resp.getWriter().write(notLogin);
            return;
        }
        // 5. 解析token,如果解析失败,返回错误结果(未登录)
        try {
            JwtUtils.parseJWT(jwt);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("令牌解析失败,返回未登录错误信息");
            Result erro = Result.error("NOT_LOGIN");
            // 手动将Result对象转化为json格式——alibaba,fastJSON
            String notLogin = JSONObject.toJSONString(erro);
            resp.getWriter().write(notLogin);
            return;
        }
        // 6. 放行
        log.info("合法,放行");
        filterChain.doFilter(servletRequest, servletResponse);
    }
}

4)拦截器Interceptor

概念: 是一种动态拦截方法调用的机制,类似过滤器。Spring框架中提供的,用来动态拦截控制器方法的执行

作用: 拦截请求,在指定的方法调用前后,根据业务需要执行预先设定的代码

@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
    @Override  // 目标资源方法运行前运行,返回true:放行,返回false:不放行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle ...");
        return true;
    }

    @Override  //目标资源方法运行后运行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle ...");
    }

    @Override  // 视图渲染完毕后运行,最后才运行
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion ...");
    }
}
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    public LoginCheckInterceptor loginCheckInterceptor;

    // 重写方法,注册拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");
    }
}

拦截路径:

在这里插入图片描述

执行流程:

在这里插入图片描述

Filter和Interceptor的区别:

  • 接口规范不同:过滤器需要实现Filter接口,而拦截器需要实现HandlerInterceptor接口
  • 拦截范围不同:过滤器Filter会拦截所有资源,而Interceptor只会拦截Spring环境中的资源

6.4 异常处理

方案一:在Controller的方法中进行try…catch处理

方案二:全局异常处理器

在这里插入图片描述

@RestControllerAdvice = @ControllerAdvice + @ResponseBody

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1368437.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构——队列(Queue)

目录 1.队列的介绍 2.队列工程 2.1 队列的定义 2.1.1 数组实现队列 2.1.2 单链表实现队列 2.2 队列的函数接口 2.2.1 队列的初始化 2.2.2 队列的数据插入&#xff08;入队&#xff09; 2.2.3 队列的数据删除&#xff08;出队&#xff09; 2.2.4 取队头数据 2.2.5 取队…

基于JAVA的教学过程管理系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 教师端2.2 学生端2.3 微信小程序端2.3.1 教师功能如下2.3.2 学生功能如下 三、系统展示 四、核心代码4.1 查询签到4.2 签到4.3 查询任务4.4 查询课程4.5 生成课程成绩 六、免责说明 一、摘要 1.1 项目介绍 基于JAVAVu…

56、Flink 的Data Source 原理介绍

Flink 系列文章 一、Flink 专栏 Flink 专栏系统介绍某一知识点&#xff0c;并辅以具体的示例进行说明。 1、Flink 部署系列 本部分介绍Flink的部署、配置相关基础内容。 2、Flink基础系列 本部分介绍Flink 的基础部分&#xff0c;比如术语、架构、编程模型、编程指南、基本的…

SpringBoot Import提示Cannot resolve symbol

背景 项目开发过程中经常在IDEA中出现Cannot resolve symbol&#xff0c;但是依赖确定已经通过maven或者gradle依赖了 常见原因 IDEA 存在缓存 File -> Invalidate Caches/Restart jar包的scope不正常&#xff0c;如果只是runtime则无法import&#xff0c;需要调整为com…

LeetCode 2221. 数组的三角和

文章目录 1. 题目 2. 解题 1. 题目 给你一个下标从 0 开始的整数数组 nums &#xff0c;其中 nums[i] 是 0 到 9 之间&#xff08;两者都包含&#xff09;的一个数字。 nums 的 三角和 是执行以下操作以后最后剩下元素的值&#xff1a; num…

一天一个设计模式---工厂方法

概念 工厂模式是一种创建型设计模式&#xff0c;其主要目标是提供一个统一的接口来创建对象&#xff0c;而不必指定其具体类。工厂模式将对象的实例化过程抽象出来&#xff0c;使得客户端代码不需要知道实际创建的具体类&#xff0c;只需通过工厂接口或方法来获取所需的对象。…

探讨JS混淆技术及其加密解密实例

引言 在当前计算机科学领域中&#xff0c;保护软件代码的安全性和隐私性变得愈发重要。为了防止黑客攻击和恶意软件分析&#xff0c;开发人员采用各种技术来混淆和加密其代码&#xff0c;其中包括JS混淆技术。本文将介绍JS混淆技术的原理和应用&#xff0c;并提供一些相关的加密…

印章管理详解|契约锁帮助提前预防99%的印章风险

传统实体印章不仅存在私刻私盖、盗用乱用、易伪造等安全隐患&#xff0c;此外&#xff0c;线下面签的方式也不便于异地、非工作时间用印&#xff0c;分公司用印常常两地来回跑。组织的印章到底怎么“管”才能保障安全和使用效率&#xff1f; 一、 印章管理风险有哪些&#xff…

Python爬虫-爬取豆瓣Top250电影信息

&#x1f388; 博主&#xff1a;一只程序猿子 &#x1f388; 博客主页&#xff1a;一只程序猿子 博客主页 &#x1f388; 个人介绍&#xff1a;爱好(bushi)编程&#xff01; &#x1f388; 创作不易&#xff1a;喜欢的话麻烦您点个&#x1f44d;和⭐&#xff01; &#x1f388;…

物理环境测评

1.1 物理位置选择 1.1.1 防震防风防雨 安全要求 机房场地选择在具有防震防风防雨等能力的建筑内 测评方法 核查是否有建筑物抗震设防审批文档 核查是否有雨水渗透的痕迹 核查是否有可灵活开启的窗户&#xff0c;若有窗户&#xff0c;是否做了封闭&#xff0c;上锁等防护措…

lua每日tips

目录 1&#xff0c;EC618系列不支持win7下刷机2&#xff0c;为何室内无法gps定位3&#xff0c;Lot平台自动锁定4&#xff0c; LuaTools的部分操作界面是支持拖拽功能的5&#xff0c;Air780E省略 1&#xff0c;EC618系列不支持win7下刷机 1&#xff0c; EC618系列不支持win7下刷…

数据结构-怀化学院期末题(322)

图的深度优先搜索 题目描述&#xff1a; 图的深度优先搜索类似于树的先根遍历&#xff0c;是树的先根遍历的推广。即从某个结点开始&#xff0c;先访问该结点&#xff0c;然后深度访问该结点的第一棵子树&#xff0c;依次为第二顶子树。如此进行下去&#xff0c;直到所有的结点…

nginx部署前端项目自动化脚本

文章目录 配置入口服务器nginx的conf.d使用docker创建一个nginx配置自动化脚本 前言 将项目 通过nginx 部署到 新的服务器 通过nginx反向代理出去 配置入口服务器nginx的conf.d 一般在这个文件夹下 找不到使用 find / -name nginx 2>/dev/null 找到nginx 的位置如果有些没有…

限制选中指定个数CheckBox控件(2/2)

实例需求&#xff1a;工作表中有8个CheckBox控件&#xff08;下文中简称为控件&#xff09;&#xff0c;现在需要实现限制用户最多只能勾选4个控件。 在上一篇博客中已经实现了这个需求&#xff0c;其基本思路是用户选中第5个控件时&#xff0c;事件代码将取消勾选最后一个选中…

Python 开源扫雷游戏 PyMine 发布介绍视频

Python 开源扫雷游戏 PyMine 发布介绍视频 Python 开源扫雷游戏 PyMine 是笔者开发的基于 wxPython 的 Python 扫雷游戏&#xff0c;现已发布介绍视频。视频请见&#xff1a;https://www.bilibili.com/video/BV1aW4y1N7Dd/ PyMine 比较忠实的还原了微软的扫雷游戏。在算法设计…

HarmonyOS应用开发者基础认证考试

判断题 1.Ability是系统调度应用的最小单元,是能够完成一个独立功能的组件。一个应用可以包含一个或多个Ability。 正确(True) 2.所有使用Component修饰的自定义组件都支持onPageShow,onBackPress和onPageHide生命周期函数。 错误(False) 3.每调用一次router.pushUrl()方法,…

【我与Java的成长记】之封装,继承详解(一)(能看懂文字就能明白系列)

系列文章目录 能看懂文字就能明白系列 C语言笔记传送门 Java笔记传送门 &#x1f31f; 个人主页&#xff1a;古德猫宁- &#x1f308; 信念如阳光&#xff0c;照亮前行的每一步 文章目录 系列文章目录&#x1f308; *信念如阳光&#xff0c;照亮前行的每一步* 前言一、封装&am…

美国NDC药品码注册详细介绍(OTC药品FDA注册)

美国药品验证号&#xff08;NDC&#xff09;注册介绍 希望我发布的文章能帮助到刷到的有缘人 国家药品验证号&#xff08;NDC&#xff09;是中国中药及OTC非处方药通过FDA认证的快捷申请形式。主要针对美国国家药典已有的药&#xff0c;无需做新药论证&#xff0c;只需提供必…

Mysql :Failed to obtain JDBC Connection

驱动版本需要跟新&#xff0c;同时驱动对应的pom依赖需要更新成mysql驱动对应版本&#xff0c;这里使用8.0.26版本。 <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql-connector}<…

C++八股学习心得.8

1.const知道吗&#xff1f;解释其作用 const 修饰类的成员变量&#xff0c;表示成员常量&#xff0c;不能被修改。 const修饰函数承诺在本函数内部不会修改类内的数据成员&#xff0c;不会调用其它非 const 成员函数。 如果 const 构成函数重载&#xff0c;const 对象只能调…