用户的登录

当用户输入用户名和密码将数据提交给后台数据库进行查询,如果存在对应的用户名和密码,则表示登录成功,登录成功之后跳转到系统的主页,就是index.html页面,跳转在前端的jQuery来完成。

1、登录持久层

        1.1规划需要执行的SQL语句:依据用户提交的用户名和密码做select查询,密码的比较在业务层执行。

        select * from t_user where username=?

        说明:如果在分析过程发现某个功能模块已经被开发完成,所以就可以省略当前的开发步骤,这个分析过程不能够省略。

        1.2接口设计和抽象方法:也不用重复开发。

        1.3单元测试也是无需单独执行。

2、登录业务层

        2.1 规划相关的异常:

                (1)用户名对应的密码错误,密码匹配失败的异常:PasswordNotMatchException异常,也属于运行时异常,也属于业务层异常。

                (2)用户名没有被找到,抛出异常:UsernameNotFoundException,也属于运行时异常,也属于业务层异常。

                (3)异常的编写:

                        1、业务层异常需要继承ServiceException异常类;

                        2、在具体的异常类中定义构造方法(可以使用快捷键生成,5个构造方法)

        2.2 设计业务层接口和抽象方法:

                (1)(关于用户模块之前已经编写出来)直接在IUserService接口中编写抽象方法,login(String username,String password);将当前登录成功的用户数据以当前用户对象的形式进行返回。状态管理:可以将数据保存在cookie或者session中,可以避免重复度很高的数据多次频繁操作数据进行获取(用户名、用户id--存放在session中,用户头像保存在cookie中)。

                (2)需要在实现类中实现父接口中的抽象方法。

                (3)在测试类中测试业务层登录的方法是否可以执行通过。

        2.3 抽象方法的实现:

                

@Override
public User login(String username, String password) {
    //1、根据用户的名称来查询用户的数据是否存在
    User result = userMapper.findByUsername(username);
    if (result == null){
        throw new UserNotFoundException("用户数据不存在!");
    }
    //2、检测用户的密码是否匹配
    //(1)先获取到数据库中的加密之后的密码;(2)然后和用户传递过来的密码进行比较;
    //在(2)步骤中不能直接比较:
    String oldPassword = result.getPassword();
    //首先获取盐值即上一次注册时自动生成的盐值,
    String salt = result.getSalt();
    //然后将用户的密码按照相同的md5算法的规则进行加密
    String newMd5Password = getMD5Password(password,salt);
    //3、将密码进行比较
    if (newMd5Password.equals(oldPassword)){
        throw new PasswordNotMatchException("用户密码错误!");
    }

    //判断is_delete字段的值是否为1表示被标记为删除
    if (result.getIsDelete() == 1){
        throw new UserNotFoundException("用户数据不存在!");
    }
    //重新new一个user对象,此处只封装三个数据。这样做法使得层与层之间数据传输的体量变小,提升了性能。
    User user = new User();
    user.setUid(result.getUid());
    user.setUsername(result.getUsername());
    user.setAvatar(result.getAvatar());

    //如果找到将当前用户的数据返回,而返回的数据是为了给其他页面展示数据用的(uid,username,avatar
    // 因为用户登录成功一般会显示id、用户名和头像等信息)
    return user;
}

3、登录控制层

        1、处理异常:业务层抛出的异常是什么?需要在统一的异常处理类中进行统一的捕获和处理;如果曾经抛出的异常类型已经在统一异常处理类中曾经处理过,则不需要重复添加;

        

else if (e instanceof UserNotFoundException) {
    result.setState(5001);
    result.setMessage("用户数据不存在的异常!");
}else if (e instanceof PasswordNotMatchException) {
    result.setState(5002);
    result.setMessage("用户名的密码错误的异常!");
}

        2、设计请求:

                (1)请求路径:/users/login

                (2)请求方式:POST

                (3)请求数据:String name, String password,HttpSession session

                (4)响应结果:JsonResult<User>;

        3、处理请求:在UserController类中编写处理请求的方法。

                

@RequestMapping("login")
public JsonResult<User> login(String username, String password){
   User data = userService.login(username,password);
    return new JsonResult<User>(OK,data);
}

4、登录前端页面

        (1)在login.html页面中依据前面所设置的请求来发送ajax请求。

        (2)访问页面进行用户的登录操作。

用户登录会话session:

session对象作用主要存储在服务器端,可以用于保存服务器的临时数据的对象,所保存的数据可以在整个项目中都可以通过访问来获取,把session中的数据看作一个共享的数据。首次登录的时候所获取到的用户的数据,转移到session对象即可。session.getAttrbute("key")可以将获取session中的数据这种行为进行封装,封装在BaseController类中。

1、封装session对象中数据的获取(只要登录成功了,获取的是当前用户的所有session数据,可以封装在父类中),数据的设置(当用户登录成功后进行数据的设置,设置到全局的session对象中)。

2、在父类中封装两个数据:获取uid和获取用户的username对应的两个方法。用户头像暂时不考虑,将来封装在cookie中来使用。

        

//因为并不知道是哪个session对象,需要设置一个session对象(需要知道从哪个session对象中获取uid)
protected final Integer getuidFromSession(HttpSession session){
    //返回当前登录的用户uid值
    //session中保存的可以是任何数据类型,cookie中只能是String类型
    //将串转化为整数使用Integer.valueOf()方法
    return Integer.valueOf(session.getAttribute("uid")
            .toString());
}

//获取当前登录用户的username
//在实现类中重写父类中的toString()方法,不是句柄信息的输出.
protected final String getUsernameFromSession(HttpSession session){
    return session.getAttribute("username").toString();
}

3、需要在登录的方法中将数据封装在session对象中。服务器本身自动创建有session对象,已经是一个全局的session对象。SpringBoot直接使用session对象,要求是直接将HttpSession类型的对象作为请求处理方法的参数,会自动将全局的session对象注入到请求处理方法的session形参上。

拦截器:可以将所有的请求统一拦截到拦截器中 ,可以在拦截器中来定义过滤的规则,如果不满足系统设置的过滤规则,统一的处理是重新去打开login.html页面(重定向和转发),推荐使用重定向。

在SpringBoot项目中做拦截器的定义和使用。SpringBoot是依靠SpringMVC来完成的。SpringMVC提供了以恶HanderInterceptor接口,用于表示定义一个拦截器。首先自定义类,然后再让类实现这个接口。

(1)首先自定义一个类,在这个类实现这个HandlerInterceptor接口。

        源码解析:

                

public interface HandlerInterceptor {
        //在调用所有处理请求的方法之前被自动调用执行的方法
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }
      //在ModelAndView对象返回之后被调用的方法
    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }
        //在整个请求所有关联的资源被执行完毕最后所执行的方法
    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}

//定义一个拦截器
public class LoginInterceptor implements HandlerInterceptor {
    /* 检测全局session对象中是否有uid数据,如果有则放行,
    如果没有则重定向到登录
    request:请求对象
    response:响应对象
    handler:处理器(url+Controller:映射)
    return:如果返回值为true表示放行当前的请求,如果为false则表示拦截当前的请求;
    * */
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws Exception {
        //HttpServletRequest对象来获取session对象
        Object obj = request.getSession().getAttribute("uid");
        if(obj == null){//说明用户没有登录过系统,则重定向到login.html
           response.sendRedirect("/web/login.html");
           //结束后续的调用
            return false;
        }
        //请求放行
        return true;
    }
}

2、注册过滤器:添加白名单(哪些资源可以在不登陆的情况下访问:login.html,register.html\login\reg\index.html\product.html)、添加黑名单(在用户登录的状态下才可以访问的页面资源)。

3、注册过滤器的技术(怎么注册过滤器):借助vcConfigure接口,可以将用户定义的拦截器进行注册,才可以保证拦截器能够生效和使用。定义一个类:然后让这个类实现WebMvcCOnfigure接口。由于是配置信息(配置类),因此建议放在项目的config包结构下。

        //将自定义的拦截器进行注册

default void addInterceptors(InterceptorRegistry registry) {
}

4、提示重定向次数过多,login.html页面无法打开,将浏览器cookie清除,再将浏览器设置为初始设置。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值