牛客网社区项目——2.6开发登录退出功能

登录

entity

首先我们看一看数据库login_ticket表,id主键,user_id,ticket也就是登录口令,还有status状态,0有效1无效,expired失效日期。根据数据库写实体类,并生成get/set方法。

	private int id;
    private int userId;
    private String ticket;
    private int status;
    private Date expired;
DAO层

然后写dao层接口,新建LoginTicketMapper。之前我们写sql是在resources下mapper目录写xml,这里来演示另一种方法——注解。

  • 首先还是@Mapper注解定义接口
  • 按照之前的方法写好抽象方法,插入登录口令
  • 在方法上加@Insert注解,对应insert方法,可以将sql语句拆分成多个字符串,同样#{}从变量中取值
  • @Options使用主键自增
  • Select方法也类似
@Mapper
public interface LoginTicketMapper {
	@Insert({
            "insert into login_ticket(user_id,ticket,status,expired) ",
            "values(#{userId},#{ticket},#{status},#{expired})"
    })
    @Options(useGeneratedKeys = true,keyProperty = "id")
    int insertLoginTicket(LoginTicket ticket);
    
    @Select({
            "select id,user_id,ticket,status,expired ",
            "from login_ticket where ticket=#{ticket}"
    })
    LoginTicket selectByTicket(String ticket);
}

第三个@Update演示动态拼接sql语句,首先用标签包裹sql语句,使用判断和拼接,这里直接拼了一个1=1。

@Update({
            "<script>",
            "update login_ticket set status=#{status} where ticket=#{ticket} ",
            "<if test=\"ticket!=null\" >",
            "and 1=1",
            "</if>",
            "</script>"
    })
    int updateStatus(String ticket,int status);
Service(业务层)

然后写登录服务,这个也算是user相关的,直接写在UserService。

  • 返回值使用map返回多种情况的消息,需要浏览器传用户名,密码,过期时间。
  • 首先对空值处理,以防浏览器错误传入空值
  • 通过用户名查出user,依次验证账号,账号状态,密码
  • 验证通过后生成登录凭证,存到数据库,并返回ticket
//登录
    public Map<String,Object> login(String username,String password,int expiredSeconds){
        Map<String,Object> 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;
    }
controller(视图层)

登录一般有记住我选项,也就是登录凭证过期时间不一样,先在CommunityConstant下定义一下不同情况的过期时间。

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

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

然后写登录的控制方法。

  • 首先访问路径/login,前面已经用过这个路径,但是因为方法不一样,这里要提交表单使用POST方法,所以可以同时存在。
  • 接收浏览器传来的用户名、密码、验证码、是否记住我,这里还要用到model、session和response
  • 首先判断验证码是否正确,从session中取出登录页面生成的验证码,返回类型是对象,强制转换为String。不正确就返回验证码错误的消息,并返回登录页面
  • 首先根据是否记住我,选择登录凭证过期时间,然后调用login,使用map接收返回的信息
  • map里有ticket说明登录成功,将ticket存入cookie通过响应发送给浏览器,并重定向到首页
  • 登录失败就返回相应错误消息,跳转到登录页
//登录验证
    @RequestMapping(path = "/login",method = RequestMethod.POST)
    public String login(String username,String password,String code,boolean rememberMe,
                        Model model,HttpSession session,HttpServletResponse response){
        String kaptcha=(String) session.getAttribute("kaptcha");
        if (StringUtils.isBlank(kaptcha)||StringUtils.isBlank(code)||!kaptcha.equalsIgnoreCase(code)){
            model.addAttribute("codeMsg","验证码不正确");
            return "/site/login";
        }

        //检查账号,密码
        int expiredSeconds=rememberMe ? REMEMBER_EXPIRED_SECONDS : DEFAULT_EXPIRED_SECONDS;
        Map<String,Object> 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";
        }
    }

配置对应的 .html 文件
1、post请求要声明提交路径
2、动态处理错误信息

退出

退出功能比较简单,只需将登录凭证修改为失效状态,LoginTicketMapper 接口中已完成了和更新状态功能和数据库的交互,因此只需完成服务层和表现层的编写即可

服务层代码

public void logout(String ticket){
        loginTicketMapper.updateStatus(ticket,1);
}

表现层代码

@RequestMapping(path = "/logout", method = RequestMethod.GET)
    public String logout(@CookieValue("ticket") String ticket){
        userService.logout(ticket);
        return "redirect:/login";
    }
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值