栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Boot项目06之用户登陆模块与登录拦截器

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Boot项目06之用户登陆模块与登录拦截器

1.登陆功能基本思路

首先,在数据库中查询这条用户记录,如果不存在这条记录则表示身份验证失败,登录流程终止;如果存在这条记录,则表示身份验证成功,接下来则需要进行登录状态的存储和验证了,用户登录成功后我们将用户信息放到 session 对象中,之后再实现一个拦截器,在访问项目时判断 session 中是否有用户信息,有则放行请求,没有就跳转到登录页面。

2.登陆页面制作 2.1 Controller控制跳转

在 BBSUserController.java类中新增跳转功能。该方法用于处理 /login 请求,是登录页面的跳转处理方法,请求方法为 GET,在发起请求后会分别跳转到 templates 模板目录中 user 目录下的 login.html 中。

    
    @GetMapping({"/login", "/login.html"})
    public String loginPage() {
        return "user/login";
    }
2.2 创建登陆页面

登录页面与注册页面非常类似,只是二者的功能有些区别而已。






6到20个字符
单击图片刷新!
忘记密码?

3. 完成登陆功能 3.1 BBSUserController层代码

这里负责接收前端传来的用户登录相关参数,包括登录邮箱、密码等;接口的映射地址为 /login,请求方法为 POST。首先对参数进行校验,之后调用 bbsUserService 业务层代码查询用户输入的登录信息是否正确,最后根据业务层的结果来返回对应的 Result 对象。

    
    @PostMapping("/login")
    @ResponseBody
    public Result login(@RequestParam("loginName") String loginName,
                        @RequestParam("verifyCode") String verifyCode,
                        @RequestParam("password") String password,
                        HttpSession httpSession) {
        if (!StringUtils.hasLength(loginName)) {
            return ResultGenerator.genFailResult(ServiceResultEnum.LOGIN_NAME_NULL.getResult());
        }
        if (!PatternUtil.isEmail(loginName)) {
            return ResultGenerator.genFailResult(ServiceResultEnum.LOGIN_NAME_NOT_EMAIL.getResult());
        }
        if (!StringUtils.hasLength(password)) {
            return ResultGenerator.genFailResult(ServiceResultEnum.LOGIN_PASSWORD_NULL.getResult());
        }
        if (!StringUtils.hasLength(verifyCode)) {
            return ResultGenerator.genFailResult(ServiceResultEnum.LOGIN_VERIFY_CODE_NULL.getResult());
        }
        String kaptchaCode = httpSession.getAttribute(Constants.VERIFY_CODE_KEY) + "";
        if (!StringUtils.hasLength(kaptchaCode) || !verifyCode.equals(kaptchaCode)) {
            return ResultGenerator.genFailResult(ServiceResultEnum.LOGIN_VERIFY_CODE_ERROR.getResult());
        }
        String loginResult = bbsUserService.login(loginName, MD5Util.MD5Encode(password, "UTF-8"), httpSession);
        //登录成功
        if (ServiceResultEnum.SUCCESS.getResult().equals(loginResult)) {
            httpSession.removeAttribute(Constants.VERIFY_CODE_KEY);//删除session中的验证码
            return ResultGenerator.genSuccessResult();
        }
        //登录失败
        return ResultGenerator.genFailResult(loginResult);
    }
3.2 BBSUserServiceImpl业务层代码

首先根据登录名和密码查询数据库中是否有对应的用户记录,不存在则返回错误信息,如果存在则将用户信息保存到 session 对象中,最后返回登录成功的业务信息。

    
    String login(String loginName, String passwordMD5, HttpSession httpSession);
    @Override
    public String login(String loginName, String passwordMD5, HttpSession httpSession) {
        BBSUser user = bbsUserMapper.selectByLoginNameAndPasswd(loginName, passwordMD5);
        if (user != null && httpSession != null) {
            // 将用户信息存入session中
            httpSession.setAttribute(Constants.USER_SESSION_KEY, user);
            //修改最近登录时间
            user.setLastLoginTime(new Date());
            bbsUserMapper.updateByPrimaryKeySelective(user);
            return ServiceResultEnum.SUCCESS.getResult();
        }
        return ServiceResultEnum.LOGIN_ERROR.getResult();
    }
3.3 BBSUserMapper数据持久层

主要的 SQL 方法为 selectByLoginNameAndPasswd(),根据用户名和密码查询用户记录信息。接着updateByPrimaryKeySelective()修改登录时间。

    BBSUser selectByLoginNameAndPasswd(@Param("loginName") String loginName, @Param("password") String password);
    int updateByPrimaryKeySelective(BBSUser record);
    
    
    
    
        update tb_bbs_user
        
            
                login_name = #{loginName,jdbcType=VARCHAR},
            
            
                password_md5 = #{passwordMd5,jdbcType=VARCHAR},
            
            
                nick_name = #{nickName,jdbcType=VARCHAR},
            
            
                head_img_url = #{headImgUrl,jdbcType=VARCHAR},
            
            
                gender = #{gender,jdbcType=VARCHAR},
            
            
                location = #{location,jdbcType=VARCHAR},
            
            
                introduce = #{introduce,jdbcType=VARCHAR},
            
            
                user_status = #{userStatus,jdbcType=TINYINT},
            
            
                last_login_time = #{lastLoginTime,jdbcType=TIMESTAMP},
            
            
                create_time = #{createTime,jdbcType=TIMESTAMP},
            
        
        where user_id = #{userId,jdbcType=BIGINT}
    
3.4 前后端交互
    layui.use(['layer', 'jquery'], function () {
        var layer = layui.layer;
        var $ = layui.$;
        window.login = function () {
            var loginName = $("#loginName").val();
            if (!validEmail(loginName)) {
                layer.alert('请输入正确的登录名!', {title: '提醒', skin: 'layui-layer-molv', icon: 2});
                return false;
            }
            var password = $("#password").val();
            if (!validPassword(password)) {
                layer.alert('请输入正确的密码格式!', {title: '提醒', skin: 'layui-layer-molv', icon: 2});
                return false;
            }
            var verifyCode = $("#verifyCode").val();
            if (!validLength(verifyCode, 5)) {
                layer.alert('请输入正确的验证码!', {title: '提醒', skin: 'layui-layer-molv', icon: 2});
                return false;
            }
            var params = $("#loginForm").serialize();
            var url = '/login';
            $.ajax({
                type: 'POST',//方法类型
                url: url,
                data: params,
                success: function (result) {
                    if (result.resultCode == 200) {
                        window.location.href = '/index';
                    } else {
                        layer.msg(result.message);
                    }
                    ;
                },
                error: function () {
                    layer.alert('操作失败!', {title: '提醒', skin: 'layui-layer-molv', icon: 2});
                }
            });
        }
    });

1.首先是用 jQuery 语法将用户输入的字段获取到

2.使用正则表达式验证用户的输入字段是否符合规范
3.封装数据并向登录接口发送 Ajax 请求
4.请求成功后会跳转至首页 /index,如果想跳转到其他页面可以在这里更改路径
5.请求失败则提醒对应的错误信息

3.5 创建一个index.html首页 3.5.1 创建一个简单首页

这里只需要创建一个简单的页面验证登陆功能即可。




    
    
    
    Document


    登陆成功!!!


3.5.2 Controller控制跳转
@Controller
public class IndexController {

    @GetMapping("/index")
    public String indexPage(){
        return "index";
    }
}
4.验证登陆功能

启动项目验证登陆功能,输入帐号 123456@qq.com,密码 123456,再输入正确的验证码,之后点击 “登录” 按钮就可以完成登录流程。效果如下展示:

5. 实现登陆拦截器

登录的目的是为了能够访问一些需要身份信息的页面,比如个人信息页面、添加文章页面,如果没有正确登录的话,是不允许正常的访问页面的,而是跳转至登录页面让用户完成登录才能够继续操作。

拦截器实现
定义一个 Interceptor 非常简单,方式也有几种,这里列举两种简单的实现:

  • 新建类实现 Spring 的 HandlerInterceptor 接口
  • 新建类继承实现了 HandlerInterceptor 接口的实现类,例如已经提供的实现了 HandlerInterceptor 接口的抽象类 HandlerInterceptorAdapter

HandlerInterceptor 方法介绍

boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception;

void postHandle(
        HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;

void afterCompletion(
        HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;
  • preHandle:在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理。
  • postHandle:在业务处理器处理请求执行完成后,生成视图之前执行。
  • afterCompletion:在 DispatcherServlet 完全处理完请求后被调用,可用于清理资源等,返回处理(已经渲染了页面)。
5.1 实现HandlerInterceptor

新建 interceptor 包,在包中新建 MyBBSLoginIntercepto 类,该类需要实现 HandlerInterceptor 接口。

@Component
public class MyBBSLoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        if (null == request.getSession().getAttribute(Constants.USER_SESSION_KEY)) {
            response.sendRedirect(request.getContextPath() + "/login");
            return false;
        } else {
            return true;
        }
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}
5.2 配置拦截器

在实现拦截器的相关方法之后,我们需要对该拦截器进行配置才能使其生效。

强调一下: 在 Spring Boot 1.x 版本中通常会继承 WebMvcConfigurerAdapter 类,但是在 Spring Boot 2.x 版本中,WebMvcConfigurerAdapter 被弃用,虽然继承 WebMvcConfigurerAdapter 这个类比较便利,但在 Spring 5.0 里面已经被弃用了,官方文档也说了,WebMvcConfigurer 接口现在已经有了默认的空白方法,所以在 Spring Boot 2.x 版本下更好的做法还是实现 WebMvcConfigurer 接口。

新建 config 包,之后新建 MyBBSWebMvcConfigurer.java 类并实现 WebMvcConfigurer 接口。

@Configuration
public class MyBBSWebMvcConfigurer implements WebMvcConfigurer {

    @Autowired
    private MyBBSLoginInterceptor myBBSLoginInterceptor;

    public void addInterceptors(InterceptorRegistry registry) {
        // 登陆拦截
        registry.addInterceptor(myBBSLoginInterceptor)
                .excludePathPatterns("/register")
                .excludePathPatterns("/login")
                .addPathPatterns("/index");
    }
}

其中 excludePathPatterns() 方法是设置请求不被拦截器拦截,而 addPathPatterns() 方法则是设置拦截器对这些请求生效,因此上述代码中,对于注册请求和登录请求是放行的,也就是访问这两个地址是不会进行 session 中是否有登录用户对象的验证,而对于 /index 请求则会判断是否已经成功登录。

6.验证拦截器

在地址栏输入index会跳转到登陆界面。

至此登陆功能和登陆拦截器功能也实现完成了。
项目源码下载地址:项目源码下载

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1040469.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号