瑞吉外卖项目(二)登录业务开发

本文详细介绍了如何在Spring Boot应用中实现后台登录功能,包括需求分析、代码开发、功能测试,并讨论了登录功能的优化,通过创建自定义过滤器实现未登录用户的权限拦截。此外,还涵盖了退出登录的实现逻辑。
摘要由CSDN通过智能技术生成

第四章 登录业务开发

后台登录功能开发

需求分析

http://localhost:8080/backend/page/login/login.html

在这个路径下,当我们点击登陆时,会发现有这样一个请求

请求 URL: http://localhost:8080/employee/login

此时报错404,是因为我们后台还没有响应这个请求的处理器,所以我们需要创建相关类来处理登录请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2KnxWSmW-1652001152484)(C:\Users\12044\Documents\实战项目\瑞吉外卖项目\瑞吉-image-06.png)]

代码开发

从前端代码中,可以得知请求为/employee/login,后端需要传给前端的数据有msg,data,code

code==1时表示登陆成功并会跳转到首页

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YMXNU6F2-1652001152485)(C:\Users\12044\Documents\实战项目\瑞吉外卖项目\瑞吉-image-07.png)]

  1. 创建实体类Employee,和数据库中employee表进行映射,这里可以用MyBatisPlus代码生成器自动生成

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SrOOplZb-1652001152486)(C:\Users\12044\Documents\实战项目\瑞吉外卖项目\瑞吉-image-08.png)]

  2. 编写完实体类后马上编写mapper(MyBatisPlus的写法),注意标记@Mapper告诉Spring是Mapper层

    @Mapper
    public interface EmployeeMapper extends BaseMapper<Employee> {}
    
  3. 编写Service层托管Mapper层,提供给Controller调用

    service接口

    public interface EmployeeService extends IService<Employee> {}
    

    serviceImpl实现类==(注意标记@Service告诉Spring是Service层)==

    @Service
    public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService {}
    
  4. 编写EmployeeController层(对应前端请求)

    注意加上@RestController注解,因为这是前后端分离项目,只需要传输json数据给前端即可

    @RestController//@RestController注解,相当于@Controller+@ResponseBody两个注解的结合,返回json数据不需要在方法前面加@ResponseBody注解了,但使用@RestController这个注解,就不能返回jsp,html页面,视图解析器无法解析jsp,html页面
    @Slf4j//开启日志
    @RequestMapping("/employee")
    public class EmployeeController {
        //这里自动装配不推荐使用字段注入,因此手动写初始方法
        private final EmployeeService employeeService;
        public EmployeeController(EmployeeService employeeService) {
            this.employeeService = employeeService;
        }
    }
    
  5. 在EmployeeController层中登录请求实现 /employee/login

    /**
     * 员工登录
     * @param request
     * @param employee
     * @return
     */
    @PostMapping("/login")
    public R<Employee> login(HttpServletRequest request, @RequestBody Employee employee){
        //1.将页面提交的密码password进行md5加密处理
        String password = employee.getPassword();
        password = DigestUtils.md5DigestAsHex(password.getBytes());
    
        //2.根据页面提交的用户名username查询数据库
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Employee::getUsername,employee.getUsername());
        Employee emp = employeeService.getOne(queryWrapper);
    
        //3.如果没有查询到则返回登陆失败结果
        if (emp==null){
            return R.error("登录失败,用户不存在");
        }
    
        //4.密码比对
        if (emp.getPassword().equals(password)){
            return R.error("登陆失败,密码错误");
        }
    
        //5.查看员工状态,如果是禁用状态则返回,员工已被禁用
        if (emp.getStatus()==0){
            return R.error("账号已被禁用");
        }
    
        //6.登陆成功,将员工id存入Session并返回登陆成功结果
        request.getSession().setAttribute("employee",emp.getId());
        return R.success(emp);
    }
    

功能测试

登录功能实现:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sC0NYjD3-1652001152486)(C:\Users\12044\Documents\实战项目\瑞吉外卖项目\瑞吉-image-09.png)]

后台退出功能开发

需求分析

当我们点击退出登录时,存在一个/logout请求

实现/logout请求

代码开发

用户点击页面中退出按钮,发送请求,请求地址为/employee/logout,请求方式为Post

只需要在Controller中创建对应的处理方法即可,具体的处理逻辑:

  1. 清理Session中的用户id
  2. 返回结果
/*
员工退出
 */
@PostMapping("/logout")
public R<String> logout(HttpServletRequest request){

    //1.清理Session中保存的当前登陆员工的id
    request.getSession().removeAttribute("employee");

    return R.success("退出成功");
}

功能测试

当我们登录时,存在Session

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4UBLFyHv-1652001152487)(C:\Users\12044\Documents\实战项目\瑞吉外卖项目\瑞吉-image-10.png)]

当退出登录时,自动清除Session数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RS8iWI4M-1652001152488)(C:\Users\12044\Documents\实战项目\瑞吉外卖项目\瑞吉-image-11.png)]

登录功能优化

问题分析

​ 由于我们没有对于首页,资源访问等进行限制,因此即便是用户没有登录,也能通过对应的url访问到项目的所有静态资源,这是十分危险的事情,因此我们需要使用过滤器或者拦截器,在过滤器或者拦截器中判断用户是否已经完成登录,如果没有登录则跳转到登录页面。

代码实现

实现步骤:

  1. 创建自定义过滤器LoginCheckFilter

    /**
     * 检查用户是否已经完成登录
     */
    @WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
    @Slf4j
    public class LoginCheckFilter implements Filter {
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response= (HttpServletResponse) servletResponse;
            log.info("拦截到请求: {}",request.getRequestURI());
            filterChain.doFilter(request,response);
        }
    }
    
  2. 在启动类上加入注解@ServletComponentScan

  3. 完善过滤器的处理逻辑

    • 获取本次请求的URI(统一资源标识符)

    • 判断本次请求是否需要处理

      /**
       * 路径匹配,检查本次请求是否需要放行
       * @param urls
       * @param requestURI
       * @return
       */
      public boolean check(String[] urls,String requestURI){
          for (String url : urls) {
              boolean match = PATH_MATCHER.match(url, requestURI);
              if(match){
                  return true;
              }
          }
          return false;
      }
      
    • 如果不需要处理,则直接放行

    • 判断登录状态,如果已登录,则直接放行

    • 如果未登录则返回未登录结果

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response= (HttpServletResponse) servletResponse;
    
        //1.获取本次请求的URI(统一资源标识符)
        String requestURI = request.getRequestURI();
    
        log.info("拦截到请求: {}",requestURI);
        //定义不需要处理的请求路径
        String[] urls = new String[]{
            "/employee/login",
            "/employee/logout",
            "/backend/**",
            "/front/**"
        };
        //2.判断本次请求是否需要处理
        boolean check = check(urls, requestURI);
    
        //3.如果不需要处理,则直接放行
        if(check){
            log.info("本次请求 {} 不需要处理",requestURI);
            filterChain.doFilter(request,response);
            return;
        }
        //4.判断登录状态,如果已登录,则直接放行
        if (request.getSession().getAttribute("employee")!=null){
            log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("employee"));
            filterChain.doFilter(request,response);
            return;
        }
        log.info("用户未登录");
        //5.如果未登录则返回未登录结果,通过输出流的方式向客户端响应数据
        response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值