crm项目问题记录:关于使用代理类处理账号登录,账号密码错误却成功登录

本文分析了一个Spring MVC应用中,由于动态代理导致登录异常处理错误的情况。当UserService的login方法抛出密码错误异常时,由于动态代理的InvocationHandler捕获了异常,未将其重新抛出,导致控制器误判为登录成功。解决方案是在InvocationHandler的catch块中重新抛出异常,确保异常能正确传递并处理。
摘要由CSDN通过智能技术生成

问题流程描述

前端

前端页面填写账号和密码,并使用post请求发送给后端.

controller控制器

控制器根据前端发过来的请求的url,确定要执行的业务是login。并根据动态代理创建service层的动态代理实现业务层login的工作。

public class UserController extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //模板模式
        System.out.println("进入到用户控制器");
        String path = request.getServletPath();
        
        if("/settings/user/login.do".equals(path)){
            login(request, response);
        }
    }

    private void login(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("进入到验证登录操作");

        //在请求与中获得账号和密码
        String loginAct=request.getParameter("loginAct");
        String loginPwd = request.getParameter("loginPwd");
        System.out.println(loginAct+"        "+loginPwd);

        //将密码进行MD5加密
        loginPwd = MD5Util.getMD5(loginPwd);
        String ip = request.getRemoteAddr();
        System.out.println("-----------ip");

        //未来业务层的开发,统一使用代理类形态的接口对象
        UserService us =(UserService) ServiceFactory.getService(new UserServiceImpl());

        try{
            User user = us.login(loginAct, loginPwd, ip);
            //向session中传入user对象
            request.getSession().setAttribute("user", user);
            //如果程序能走到这里说明已经拿回了正确的user,则直接传入success
            PrintJson.printJsonFlag(response,true);
        }catch (Exception e){
            e.printStackTrace();
            //如果程序走到了这里就说明我们的程序没有在数据库中拿到对应的对象,说明登陆失败
            //我们需要传入失败的原因,也就是我们抛出的异常的msg
            String msg = e.getMessage();
            Map<String, Object> map=new HashMap<>();
            map.put("success", false);
            map.put("msg", msg);
            PrintJson.printJsonObj(response, map);
        }
    }
}

service层

service层中使用login函数在dao底层中查询数据库,筛选匹配的涌弧信息。因为密码是故意输错的,所以dao层没有查询到用户.dao层返回的对象是一个空值。空值在service层中的逻辑判断出抛出自定异常,提示账号密码错误。但是最终却能正常的登录产生跳转。

  @Override
    public User login(String loginAct, String loginPwd, String ip) throws LoginException {

       Map<String, String> map = new HashMap<>();
       map.put("loginAct", loginAct);
       map.put("loginPwd", loginPwd);

       User user =userDao.login(map);

       if(user == null){
           throw new LoginException("账号密码错误");
       }
       //如果程序运行到此处说明账户密码是正确豆的,则还需要验证以下三项
       //1、验证失效时间

       String expireTime = user.getExpireTime();
        System.out.println(expireTime);
       String currentTime = DateTimeUtil.getSysTime();
       if(expireTime.compareTo(currentTime) < 0){
            throw new LoginException("账号已失效");
       }

       //判断账号状态
       String lockState = user.getLockState();
       if("0".equals(lockState)){
           throw  new LoginException("账号已锁定");
       }


//       //判断IP地址 0:0:0:0:0:0:0:1
//       String allowIp = user.getAllowIps();
//        System.out.println(allowIp);
//        System.out.println(ip);
//
//       if(!allowIp.contains(ip)){
//           throw new LoginException("ip不允许");
//       }


        return user;
    }

动态代理

public class TransactionInvocationHandler implements InvocationHandler {
    private Object target;

    public TransactionInvocationHandler(Object target){
        this.target = target;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        SqlSession sqlSession = null;
        Object  obj = null;

        try{
            sqlSession = SqlSessionUtil.getSqlSession();
            //实现目标类的方法
            obj = method.invoke(target, args);
            //做功能增强,提交事务
            sqlSession.commit();
        }catch(Exception e){
            sqlSession.rollback();
            e.printStackTrace();

            //注意这里加入这个是为了防止目标类的异常被代理类捕获,所以需要再一次抛出已捕捉到的异常
           // throw e.getCause();
        }finally {
            SqlSessionUtil.myClose(sqlSession);
        }

        return obj;
    }


    public Object getProxy(){

        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this );
    }

问题分析

原因是我在controller层中为userService实现了动态代理的机制。该代理类调用login函数,在login函数中抛出了密码错误的异常,但是目标类的异常在InovactionHandeller中的invoke方法上捕获了,导致没有异常发生,所以在最后认为是登陆成功。

解决办法

在InvocationHandellor中的invoke方法中的catch代码块中将捕捉到的异常再次抛出。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值