牛客网项目5:登录、退出功能

1. 访问登录页面

点击顶部区域内的连接,打开登陆页面。

index.html中:

<li class="nav-item ml-3 btn-group-vertical">
    <a class="nav-link" th:href="@{/login}">登录</a>
</li>

2. 登录

          - 验证账号、密码、验证码;

          - 成功时:生成登录凭证,发送给客户端;

          - 失败时:跳转回登录页。

登录凭证对应的表:login_ticket

字段:id、user_id、ticket字符串凭证、status当前是否过期、expired过期时间

1> 创建 login_ticket表对应的实体类

在entity目录下,新建类:LoginTicket

//登录凭证对应的表:login_ticket
public class LoginTicket {
    private int id;
    private int userId;
    private String ticket;
    private int status;
    private Date expired;

    //get()、set()
    //toString()
}

2> 创建接口 LoginTicketMapper

用来对 login_ticket表 进行增删改查。

在dao目录下新建接口:LoginTicketMapper

//这里的SQL语句没有写mapper对应的xml文件,而是采用了注解的方式
@Mapper
public interface LoginTicketMapper {
    //插入数据
    @Insert({
            "insert into login_ticket (user_id, ticket, status, expired) ",
            "values (#{userId},#{ticket},#{status},#{expired})"
    })
    @Options(useGeneratedKeys = true, keyProperty = "id") //将id属性设为自动生成主键
    int insertLoginTicket(LoginTicket loginTicket);

    //根据 ticket 字段查询
    @Select({
            "select id,user_id,ticket,status,expired ",
            "from login_ticket where ticket=#{ticket}"
    })
    LoginTicket selectByTicket(String ticket);

    //根据 ticket 更新状态
    //这里是动态SQL的写法
    //@Update({
    //        "update login_ticket set status=#{status} where ticket=#{ticket} "
    //})
    @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);
}

在写完SQL方法后,最好先测试一波:

在测试类中编写以下测试方法

    //测试插入方法
    @Autowired
    private LoginTicketMapper loginTicketMapper;

    @Test
    public void test3(){
        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 test4(){
        LoginTicket loginTicket = loginTicketMapper.selectByTicket("abc");
        System.out.println(loginTicket);

        loginTicketMapper.updateStatus("abc",1);
        loginTicket = loginTicketMapper.selectByTicket("abc");
        System.out.println(loginTicket);
    }

3> 登录业务

为业务层操作,在service.UserService类下,创建登录方法:

    @Autowired
    private LoginTicketMapper loginTicketMapper;


    //登录业务方法
    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;
    }

4> 控制器方法

与前端进行交互。写在 LoginController控制器类下。

根据用户输入的密码、验证码判断是否登录成功。

         - 登录成功,返回到首页;

         - 登陆失败,返回到登录页面。

若用户选定 【记住我】,则登录信息保存100天。

 

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


    @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 ? DEFAULT_EXPIRED_SECONDS : REMEMBER_EXPIRED_SECONDS;
        Map<String,Object> map = userService.login(username, password, expiredSeconds);
        //成功登录:将登陆凭证存进cookie
        if(map.containsKey("ticket")){
            //cookie中存的为字符串
            Cookie cookie = new Cookie("ticket",map.get("ticket").toString());
            cookie.setPath(contextPath);       //cookie生效路径为整个项目
            cookie.setMaxAge(expiredSeconds);  //cookie生效时间
            response.addCookie(cookie);        //响应时,会将cookie发送到浏览器
            return "redirect:/index";
        }//失败
        else{
            model.addAttribute("usernameMsg",map.get("usernameMsg"));
            model.addAttribute("passwordMsg",map.get("passwordMsg"));
            return "/site/login";
        }
    }

用户信息存储时间的设置:

CommunityConstant接口中添加常量:

    //默认状态的登录凭证超时时间:默认存12小时
    int DEFAULT_EXPIRED_SECONDS = 3600 * 12;
    //记住状态下的登录凭证超时时间:100天
    int REMEMBER_EXPIRED_SECONDS = 3600 * 24 * 100;

总结:

        登录时,我们根据前端传来的地址调用了 login() 控制器方法,此方法又调用了业务层UserService的 login() 方法,进行一系列业务操作。

3. 退出

         - 将登陆凭证修改失效状态;

         - 跳转至网站首页。

1> 退出业务

为业务层操作,在service.UserService类下,创建退出方法:

    //退出登录:将凭证改为1,即失效状态
    public void logout(String ticket){
        loginTicketMapper.updateStatus(ticket,1);
    }

2> 控制器方法

LoginController控制器类下创建:

    //退出登录
    @RequestMapping(path = "/logout", method = RequestMethod.GET)
    public String logout(@CookieValue("ticket") String ticket){
        //上面登录时,把ticket放进了cookie
        userService.logout(ticket);
        return "redirect:/login";
    }

3> html页面

<a class="dropdown-item text-center" th:href="@{/logout}">退出登录</a>

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,退出登录功能通常是在用户完成操作后主动退出当前账号或系统的功能。实现退出登录功能的一种常见方式是使用会话管理机制,例如使用Session来跟踪用户的登录状态。 以下是一个简单的Java退出登录功能的实现示例: 1. 创建一个LogoutServlet类,继承自HttpServlet类,并重写doGet或doPost方法。 ```java import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; public class LogoutServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); session.invalidate(); // 销毁当前会话 response.sendRedirect("login.jsp"); // 重定向到登录页面 } } ``` 2. 在web.xml文件中配置LogoutServlet的映射路径。 ```xml <servlet> <servlet-name>LogoutServlet</servlet-name> <servlet-class>com.example.LogoutServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LogoutServlet</servlet-name> <url-pattern>/logout</url-pattern> </servlet-mapping> ``` 3. 在登录页面或其他需要退出登录的地方,添加一个退出登录的链接或按钮,指向LogoutServlet的映射路径。 ```html <a href="/logout">退出登录</a> ``` 这样,当用户点击退出登录链接时,会调用LogoutServlet的doGet方法,销毁当前会话并重定向到登录页面。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值