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

仿牛客学习论坛之登录部分

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

仿牛客学习论坛之登录部分

用户登录部分

本部分代码来源于牛客网官方的仿牛客论坛项目,仅供个人学习和探讨使用。

文章目录

用户登录部分

1 创建数据库2 编写实体类3 编写dao层4 测试dao层代码5 在util包中设置登录凭证时间6 编写service业务层7 编写controller层8 编写前端代码

1 创建数据库
DROp TABLE IF EXISTS `login_ticket`;
SET character_set_client = utf8mb4 ;
CREATE TABLE `login_ticket` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `ticket` varchar(45) NOT NULL,
  `status` int(11) DEFAULT '0' COMMENT '0-有效; 1-无效;',
  `expired` timestamp NOT NULL,
  PRIMARY KEY (`id`),
  KEY `index_ticket` (`ticket`(20))
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

相关参数说明:
id:标识唯一的登录凭证,自增
user_id:外键,通过这个值找到对应的用户
ticket:登录凭证,生成随机的字符串,唯一
status:登录状态,0-有效,1-无效
expired:登录到期时间

2 编写实体类
public class LoginTicket {
    private int id;
    private int userId;
    private String ticket; // 登录凭证
    private int status;
    private Date expired;
	// 省略 getter setter 和 toString 方法 
}
3 编写dao层

编写sql语句。

复制代码记得更改包名。

package com.zcq.community.dao;

import com.zcq.community.entity.LoginTicket;
import org.apache.ibatis.annotations.*;

@Mapper
public interface LoginTicketMapper {

    // 使用sql语句注解会比较直观,但是复杂的sql语句推荐使用xml
    @Insert({
            "insert into login_ticket(user_id, ticket, status, expired) ",
            "values(#{userId}, #{ticket}, #{status}, #{expired}) "
    })
    @Options(useGeneratedKeys = true, keyProperty = "id") // 是否启用主键,将主键注入到哪个属性中
    int insertLoginTicket(LoginTicket loginTicket);

    
    @Select({
            "select id, user_id, ticket, status, expired ",
            "from login_ticket where ticket = #{ticket} "
    })
    LoginTicket selectByTicket(String ticket);

    
    @Update({
            "update login_ticket set status = #{status} where ticket = #{ticket} ",
    })
    int updateStatus(String ticket, int status);

    // 通过注解方式也可以嵌套动态sql语句,比如if标签
        

}

4 测试dao层代码

由于注解sql语句的方式IDEA无法进行识别,如果出现语法错误会导致后续无法进行。

package com.zcq.community.dao;

import com.zcq.community.CommunityApplication;
import com.zcq.community.entity.LoginTicket;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Date;

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class LoginMapperTests {

    @Autowired
    private LoginTicketMapper loginTicketMapper;

    @Test
    public void testInsertLoginTicket() {
        LoginTicket loginTicket = new LoginTicket();
        loginTicket.setUserId(101);
        loginTicket.setTicket("abc");
        loginTicket.setStatus(0);
        loginTicket.setExpired(new Date(System.currentTimeMillis() + 1000*60*10));
        loginTicketMapper.insertLoginTicket(loginTicket);
    }

    @Test
    public void testSelectLoginTicket() {
        LoginTicket loginTicket = loginTicketMapper.selectByTicket("abc");
        System.out.println(loginTicket);
        loginTicketMapper.updateStatus("abc", 1);
        loginTicket = loginTicketMapper.selectByTicket("abc");
        System.out.println(loginTicket);
    }
}

5 在util包中设置登录凭证时间
package com.zcq.community.util;

public interface CommunityConstant {

    // 默认状态的登录凭证超时时间
    int DEFAULT_EXPIRED_SEConDS = 3600 * 12;

    // 记住状态下的登录凭证超时时间
    int REMEMBER_EXPIRED_SEConDS = 3600 * 24 * 100;
    
}

6 编写service业务层

放入 userService 中是因为登录操作与用户相关。

package com.zcq.community.service;

import com.zcq.community.dao.LoginTicketMapper;
import com.zcq.community.dao.UserMapper;
import com.zcq.community.entity.LoginTicket;
import com.zcq.community.entity.User;
import com.zcq.community.util.CommunityConstant;
import com.zcq.community.util.CommunityUtil;
import com.zcq.community.util.MailClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

@Service
public class UserService implements CommunityConstant {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LoginTicketMapper loginTicketMapper;

	// 此处省略了userService的其他代码

    public Map login(String username, String password, int expiredSeconds) {
        Map map = new HashMap<>();
        // 空值的处理
        if (StringUtils.isBlank(username)) {
            map.put("usernameMsg", "账号不能为空");
            return map;
        }
        if (StringUtils.isBlank(password)) {
            map.put("passwordMsg", "密码不能为空");
            return map;
        }

        // 验证账号
        User user = userMapper.selectByName(username);
        if(user == null) {
            map.put("usernameMsg", "该账号不存在");
            return map;
        }

        // 验证状态
        if(user.getStatus() == 0) {
            map.put("usernameMsg", "该账号未激活");
            return map;
        }

        // 验证密码
        password = CommunityUtil.md5(password + user.getSalt());
        if(!user.getPassword().equals(password)) {
            map.put("passwordMsg", "密码不正确");
            return map;
        }

		// 如果走到这里证明信息正确, 此时允许用户登录
        // 生成登录凭证
        LoginTicket loginTicket = new LoginTicket();
        loginTicket.setUserId(user.getId());
        loginTicket.setTicket(CommunityUtil.generateUUID());
        loginTicket.setStatus(0);
        loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000));
        loginTicketMapper.insertLoginTicket(loginTicket);

        map.put("ticket", loginTicket.getTicket());

        return map;
    }
}

7 编写controller层
package com.zcq.community.controller;

import com.google.code.kaptcha.Producer;
import com.zcq.community.service.UserService;
import com.zcq.community.util.CommunityConstant;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.cookievalue;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Map;

@Controller
public class LoginController implements CommunityConstant {

    @Autowired
    private UserService userService;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    // 说明:特殊对象, 比如 user, springmvc 会将值装到 model 层里, 龚前端页面获取
    // 其余参数可以从 request 中取值, 或者存到 model 层里, 从 model 层里取值
    // 这里选用 post 请求的原因是我们需要传入一个表单
    @RequestMapping(path = "/login", method = RequestMethod.POST)
    public String login(String username, String password, String code, boolean rememberme,
                        Model model, HttpSession session, HttpServletResponse response) {
        // 1 判断验证码正确与否
        String kaptcha = (String) session.getAttribute("kaptcha");
        // 后台的验证码为空 或 用户传入的验证码为空 或 忽略大小写后的值不等
        if(StringUtils.isBlank(kaptcha) || StringUtils.isBlank(code) || !kaptcha.equalsIgnoreCase(code)) {
            model.addAttribute("codeMsg", "验证码不正确");
            return "/site/login";
        }
        // 2 检查账号,密码
        int expiredSeconds = rememberme ? REMEMBER_EXPIRED_SEConDS : DEFAULT_EXPIRED_SECONDS;
        Map map = userService.login(username, password, expiredSeconds);
        if(map.containsKey("ticket")) {
            cookie cookie = new cookie("ticket", map.get("ticket").toString());
            cookie.setPath(contextPath);
            cookie.setMaxAge(expiredSeconds);
            response.addcookie(cookie);
            return "redirect:/index";
        } else {
            model.addAttribute("usernameMsg", map.get("usernameMsg"));
            model.addAttribute("passwordMsg", map.get("passwordMsg"));
            return "/site/login";
        }

    }

}

8 编写前端代码

说明:html 代码中的设计部分已删除,此处指展示和后端业务交互的部分。



	
		
		
	
	
		
该账号不存在
密码长度不能小于8位!
验证码不正确!
忘记密码?

代码编写完毕,可以进行测试了。

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

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

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