Design and Implementation of an Online Course Purchase System(29)

Complete user login function

Posted by Chen Xingxu on June 3, 2020

易课寄在线购课系统开发笔记(二十九)–完成用户登录功能

用户登录

功能分析

请求的 url:/user/login

请求的方法:POST

参数:username、password,表单提交的数据,可以使用方法的形参接收。

返回值:JSON 数据,使用 ECoursesResult 包含一个 token。

业务逻辑:

登录的业务流程:

登录的处理流程:

1、登录页面提交用户名密码;

2、登录成功后生成 token。token 相当于原来的 jsessionid,字符串,可以使用 uuid;

3、把用户信息保存到 Redis。key 就是 token,value 就是 EcoursesUser 对象转换成 JSON;

4、使用 String 类型保存 Session 信息。可以使用 “前缀: token” 为 key;

5、设置 key 的过期时间。模拟 Session 的过期时间,一般为半小时;

6、把 token 写入 Cookie 中;

7、Cookie 需要跨域。例如 www.ecourses.cn \ sso.ecourses.cn \ order.ecourses.cn,可以使用工具类;

8、Cookie 的有效期为关闭浏览器失效;

9、登录成功。

Dao层

查询 ecourses_user 表。单表查询。可以使用逆向工程。

Service层

参数:

1、用户名:String username

2、密码:String password

返回值:ECoursesResult,包装 token。

业务逻辑:

1、判断用户名密码是否正确;

2、登录成功后生成 token。token 相当于原来的 jsessionid,字符串,可以使用 uuid;

3、把用户信息保存到 Redis。key 就是 token,value 就是 EcoursesUser 对象转换成 JSON;

4、使用 String 类型保存 Session 信息。可以使用 “前缀: token” 为key;

5、设置 key 的过期时间。模拟 Session 的过期时间。一般为半小时;

6、返回 ECoursesResult 包装 token。

@Override
public ECoursesResult userLogin(String username, String password) {
    // 1、判断用户和密码是否正确
    //根据用户名查询用户信息
    EcoursesUserExample example = new EcoursesUserExample();
    Criteria criteria = example.createCriteria();
    criteria.andUsernameEqualTo(username);
    //执行查询
    List<EcoursesUser> list = userMapper.selectByExample(example);
    if (list == null || list.size() == 0) {
        //返回登录失败
        return ECoursesResult.build(400, "用户名或密码错误");
    }
    //取用户信息
    EcoursesUser user = list.get(0);
    //判断密码是否正确
    if (!DigestUtils.md5DigestAsHex(password.getBytes()).equals(user.getPassword())) {
        // 2、如果不正确,返回登录失败
        return ECoursesResult.build(400, "用户名或密码错误");
    }
    // 3、如果正确生成token。
    String token = UUID.randomUUID().toString();
    // 4、把用户信息写入redis,key:token value:用户信息
    user.setPassword(null);
    jedisClient.set("SESSION:" + token, JsonUtils.objectToJson(user));
    // 5、设置Session的过期时间
    jedisClient.expire("SESSION:" + token, SESSION_EXPIRE);
    // 6、把token返回

    return ECoursesResult.ok(token);
}

发布服务

<dubbo:service interface="cn.ecourses.sso.service.LoginService" ref="loginServiceImpl" timeout="600000"/>

表现层

引用服务:

<dubbo:reference interface="cn.ecourses.sso.service.LoginService" id="loginService" />

Controller

请求的 url:/user/login

请求的方法:post

参数:username、password,表单提交的数据。可以使用方法的形参接收。

HttpServletRequest、HttpServletResponse

返回值:JSON 数据,使用 ECoursesResult 包含一个 token。

业务逻辑:

1、接收两个参数;

2、调用 Service 进行登录;

3、从返回结果中取 token,写入 Cookie。Cookie 要跨域。

Cookie 二级域名跨域需要设置:

1)setDomain,设置一级域名:

.ecourses.cn

2)setPath。设置为“/”

工具类放到 ecourses-common 工程中。

4、响应数据。JSON 数据。ECoursesResult,其中包含 token。

@RequestMapping(value="/user/login", method=RequestMethod.POST)
@ResponseBody
public ECoursesResult login(String username, String password,
        HttpServletRequest request, HttpServletResponse response) {
    ECoursesResult ecoursesResult = loginService.userLogin(username, password);
    //判断是否登录成功
    if(ecoursesResult.getStatus() == 200) {
        String token = ecoursesResult.getData().toString();
        System.out.println(token);
        System.out.println(TOKEN_KEY);
        //如果登录成功需要把token写入cookie
        CookieUtils.setCookie(request, response, TOKEN_KEY, token);
    }
    //返回结果
    return ecoursesResult;
}