京淘day18-单点登录业务实现

1. 用户注册实现

1.1 业务需求说明

说明: 当用户点击新增按钮时,应该将数据由jt-web服务器,传递给jt-sso项目完成入库操作.同时返回有效信息进行校验.
京淘day18-单点登录业务实现_第1张图片

1.2 页面分析

1).url分析
京淘day18-单点登录业务实现_第2张图片

1.3 编辑JT-WEB UserController

 /**
     * 完成用户注册操作
     * 1.url地址:http://www.jt.com/user/doRegister
     * 2.参数:   password: admin123
     *           username: admin12332412341234
     *           phone: 13111112227
     * 3.返回值:  SysResult对象
     */
    @RequestMapping("/doRegister")
    @ResponseBody   //将返回值结果转化为JSON
    public SysResult saveUser(User user){

        userService.saveUser(user);
        return SysResult.success();
    } 

1.4 编辑JT-SSO UserService

package com.jt.service;
import com.alibaba.dubbo.config.annotation.Service;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import sun.security.provider.MD5;
@Service
public class DubboUserServiceImpl implements DubboUserService{
    @Autowired
    private UserMapper userMapper;
    /**
     * 业务:
     *  1.将密码进行加密处理
     *  2. 邮箱暂时用电话代替
     * @param user
     */
    @Override
    public void saveUser(User user) {

        byte[] bytes = user.getPassword().getBytes();
        //利用Spring工具API进行加密操作
        String md5Pass = DigestUtils.md5DigestAsHex(bytes);
        user.setPassword(md5Pass).setEmail(user.getPhone());
        userMapper.insert(user);
    }
} 

2 用户登录实现

2.1 业务需求

要求: 用户只需要登录一次,则可以在任意的服务器享受免密登录.有效期为30天.
sso介绍:
单点登录(SingleSignOn,SSO),就是通过用户的一次性鉴别登录。当用户在身份认证服务器上登录一次以后,即可获得访问单点登录系统中其他关联系统和应用软件的权限,同时这种实现是不需要管理员对用户的登录状态或其他信息进行修改的,这意味着在多个应用系统中,用户只需一次登录就可以访问所有相互信任的应用系统。这种方式减少了由登录产生的时间消耗,辅助了用户管理,是目前比较流行的 [1]

2.2 单点登录实现原理

京淘day18-单点登录业务实现_第3张图片
单点登录实现步骤:
1.用户通过用户名和密码访问jt-web服务器.
2.JT-WEB服务器通过JT-SSO校验用户名和密码是否正确.
3.如果用户名和密码正确,则将数据保存到redis中. TICKET密钥:USERJSON,之后将密钥返回给用户即可.
4.JT-WEB服务器将密钥信息保存到用户的Cookie中 并且设定Cookie的共享/有效时间.

2.3 登录页面分析

1).url分析
京淘day18-单点登录业务实现_第4张图片

2.4 编辑UserController

 /**
     * 业务需求:
     *   实现用户单点登录操作
     *   1.url地址:http://www.jt.com/user/doLogin?r=0.43530970885614617
     *   2.请求参数:  username: asdasdfas
     *                password: asdfasdfa
     *   3.返回值结果: SysResult对象
     *
     * 实现Cookie数据存储
     *  1.获取用户名和密码进行数据校验
     *  2.获取后端的密钥信息  非空????
     *  3.如果一切正常,则将数据存储到Cookie中. 路径/有效期/共享问题
     *
     * 关于Cookie说明:
     *      1.cookie只能看到自己域名下的cookie   私有的.
     *      2.setPath说明
     *          setPath("/") 一般都是/  读取cookie权限的设定,根目录中的请求 读取cookie
     *          setPath("/user") url地址路径/user下时才能获取cookie信息.
     *          url1: http://www.jt.com/findUser;
     *          url2: http://www.jt.com/user/findUser;
     *
     */
    @RequestMapping("/doLogin")
    @ResponseBody
    public SysResult userLogin(User user, HttpServletResponse response){
        String ticket = userService.findUserByUP(user);
        if(!StringUtils.hasLength(ticket)){
            //如果数据为null则表示用户名和密码错误...
            return SysResult.fail();
        }

        //需要将数据保存到cookie中
        Cookie cookie = new Cookie("JT_TICKET", ticket);
        cookie.setPath("/");
        cookie.setMaxAge(7*24*60*60); //设定有效期 7天有效 单位秒
        cookie.setDomain("jt.com");   //主要域名中由jt.com则可以共享数据
        response.addCookie(cookie);   //将数据写入客户端
        return SysResult.success();
    }

2.5 编辑UserService

/**
     * 1.校验用户名和密码是否正确  不存在直接返回null
     * 2.动态生成密钥   将用户信息转化为JSON
     * 3.将数据保存到redis中 7天有效.
     * 4.返回密钥ticket信息.
     * @param user
     * @return
     */
    @Override
    public String findUserByUP(User user) {
        String md5Pass =
                DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
        user.setPassword(md5Pass);
        //1.根据对象中不为null的属性当做where条件
        QueryWrapper queryWrapper = new QueryWrapper<>(user);
        User userDB = userMapper.selectOne(queryWrapper);

        //2.判断对象是否有值
        if(userDB==null){
            return null;
        }

        //3.表示用户名和密码正确 开启单点登录操作
        String ticket = UUID.randomUUID()
                        .toString().replace("-", "");
        //转化之前应该将数据进行脱敏处理
        userDB.setPassword("123456");
        String userJSON = ObjectMapperUtil.toJSON(userDB);

        //4.将数据保存到redis中
        jedisCluster.setex(ticket, 7*24*60*60, userJSON);
        return ticket;
    }

2.6 效果测试

京淘day18-单点登录业务实现_第5张图片

3 用户数据回显

3.1 业务分析

如果用户登录成功之后,则通过cookie数据利用JSONP跨域方式,实现数据的动态获取.

3.2 页面URL分析

1).页面URL分析
京淘day18-单点登录业务实现_第6张图片

3.3 编辑JT_SSO UserController

/**
     * 跨域请求:完成用户信息获取
     * URL网址:  http://sso.jt.com/user/query/dca70b16a1c54aea9ebb0b27621250de?callback=jsonp1608021961735&_=1608021961777
     * 参数:    参数1: ticket信息    参数2:callback
     * 返回值:   SysResult对象(用户数据......)
     */
    @RequestMapping("/query/{ticket}")
    public JSONPObject findUserByTicket(@PathVariable String ticket,
                                        String callback){
        //如何获取用户信息?  从redis中获取数据
        if(jedisCluster.exists(ticket)){
            String userJSON = jedisCluster.get(ticket);
            SysResult sysResult = SysResult.success(userJSON);
            return new JSONPObject(callback, sysResult);
        }else{
            return new JSONPObject(callback, SysResult.fail());
        }
    }

4. 完成用户退出操作

4.1 业务说明

1).当用户点击退出按钮时,应该重定向到系统首页
2).删除redis中的数据
3).删除Cookie中的数据

4.2 编辑UserController

 /**
 * 完成用户退出操作
 * 1.重定向到系统首页
 * 2.要求删除redis中的数据  K-V结构  先获取key
 * 3.动态获取Cookie中的数据
 * 4.删除Cookie中的数据
 * url地址: http://www.jt.com/user/logout.html
 * */
    @RequestMapping("/logout")
    public String logout(HttpServletRequest request,HttpServletResponse response){
      Cookie[] cookies = request.getCookies();
      if(cookies !=null && cookies.length>0){
          for (Cookie cookie : cookies){
              if(JT_TICKET.equals(cookie.getName())){
                  String ticket = cookie.getValue();
                  //删除redis的数据
                  jedisCluster.del(ticket);
                  //删除cookie的数据
                  cookie.setMaxAge(0); //0 立即删除  -1 关闭浏览器之后删除
                  cookie.setPath("/");
                  cookie.setDomain("jt.com");
                  response.addCookie(cookie);
              }
          }
      }
        return "redirect:/";
    }

4.3 封装工具API

作用: API主要的作用 简化Cookie调用的过程. 1.获取Cookie对象 2.可以根据cookieName 获取cookie的值 3.新增cookie 删除cookie

public class CookieUtil {
    //1.获取cookie对象
    public static Cookie getCookie(HttpServletRequest request,String cookieName){
        Cookie[] cookies = request.getCookies();
        if(cookies !=null && cookies.length>0){
            for(Cookie cookie : cookies){
               if(cookieName.equals(cookie.getName())){
                   return cookie;
               }
            }
        }
        return null;
    }
    //2.获取Cookie值
    public static String getCookieValue(HttpServletRequest request,String cookieName){
        Cookie cookie = getCookie(request,cookieName);
        return cookie ==null?null:cookie.getValue();
    }
    //3.新增Cookie/删除Cookie写法
    public static void addCookie(HttpServletResponse response,String cookieName,String cookieValue,String path,String domain,Integer seconds){
        Cookie cookie = new Cookie(cookieName,cookieValue);
        cookie.setPath(path);
        cookie.setDomain(domain);
        cookie.setMaxAge(seconds);
        response.addCookie(cookie);
    }
}

4.4 重构UserController 完成退出操作

 /**
 * 完成用户退出操作
 * 1.重定向到系统首页
 * 2.要求删除redis中的数据  K-V结构  先获取key
 * 3.动态获取Cookie中的数据
 * 4.删除Cookie中的数据
 * url地址: http://www.jt.com/user/logout.html
 * */
    @RequestMapping("/logout")
    public String logout(HttpServletRequest request,HttpServletResponse response){
        String ticket = CookieUtil.getCookieValue(request, JT_TICKET);
        if(StringUtils.hasLength(ticket)){
            //1.删除redis
            jedisCluster.del(ticket);
            //2.删除cookie
            CookieUtil.addCookie(response,JT_TICKET,
                    "", "/", "jt.com", 0);
        }
        return "redirect:/";
      /*Cookie[] cookies = request.getCookies();
      if(cookies !=null && cookies.length>0){
          for (Cookie cookie : cookies){
              if(JT_TICKET.equals(cookie.getName())){
                  String ticket = cookie.getValue();
                  //删除redis的数据

你可能感兴趣的:(springboot)