登录带session到页面_单点登录SSO基于缓存的使用

  1. 首先我创建了一个SpringCloud项目,项目分层分别如下:

    33181113f39355763a4247c20ac8c4ed.png

    其中sso_common是公共调用模块~

  2. 创建前台,后台的重定向跳转,前台页面滤过。。。

  3. 首先测试一下,在首页点登录是否能够正常跳到登陆页面(这里携带了本次路径的参数)

    40bc9a33990a1ed89835d2142ef7ef44.png

  4. 而这里重点说下后台的写法,首先是需要在后台的viewcontroller层重定向跳转页面的:

//跳转到登录页面//@RequestParam(required = false,defaultValue = ""   这个参数可能不存在,就定义为空@GetMapping("/login")public String login(@RequestParam(required = false,defaultValue = "") String target,HttpSession session){    if (StringUtils.isEmpty(target)){        target="http://127.0.0.1:9010";//跳转到首页    }    //这里还是需要做地址的校验的额    session.setAttribute("target",target);//存在session中    return "login";}

    5.这时候session中就有target的值了,接下来在点击登录按钮的时候触发form表单中的post请求,跳到登录的Controller层:

@PostMappingpublic String Login(User user,HttpSession session){    String target = (String) session.getAttribute("target");    //模拟一下登录    Optional first = dbuser.stream().filter(dbuser -> dbuser.getUsername().equals(user.getUsername()) &&                                                  dbuser.getPassword().equals(user.getPassword())).findFirst();    //判断first里面是否有值    if(first.isPresent()){        //随机生成一个token        String token = UUID.randomUUID().toString();        //保存用户的信息        LoginCacheUtil.logionUser.put(token,first.get());    }else {        //登陆失败        session.setAttribute("msg","登陆失败,或是密码错误~~啦啦啦");        return "login";    }    //重定向到target页面中去    return "redirect:"+target;}

    6.解释一下这里的LoginCacheUtil.logionUser它是一个自己定义的工具类,把登录的信息存到了一个map中

package com.sso.login.util;import com.sso.login.pojo.User;import java.util.HashMap;import java.util.Map;/** * @Author:dada * @Date:2020/10/31 19:01 * @Version 1.0 *///保存用户信息public class LoginCacheUtil {    public static Map logionUser = new HashMap<>();}

    7.声明一下dbuser模拟一下数据库的数据

//模拟一下数据库中的数据private static Setdbuser;static {    dbuser=new HashSet<>();    dbuser.add(new User(0,"zhangsan","12345"));    dbuser.add(new User(1,"lisi","123456"));    dbuser.add(new User(2,"wangwu","1234567"));}

    8.然后在方法中定义一个HttpServletResponse参数,作为相应给浏览器

Cookie cookie = new Cookie("TOKEN", token);

    9.cookie要在系统中之间互相访问,这时候他们的域就应该是一样的

cookie.setDomain("127.0.0.1")//相应出去response.addCookie(cookie);

    10.完整的login的接口:

@PostMappingpublic String Login(User user, HttpSession session, HttpServletResponse response){    String target = (String) session.getAttribute("target");    //模拟一下登录    Optional first = dbuser.stream().filter(dbuser -> dbuser.getUsername().equals(user.getUsername()) &&                                                  dbuser.getPassword().equals(user.getPassword())).findFirst();    //判断first里面是否有值    if(first.isPresent()){        //随机生成一个token        String token = UUID.randomUUID().toString();        //然后方法中定义一个HttpServletResponse参数,然后让response相应出去        Cookie cookie = new Cookie("TOKEN", token);        //cookie要在子系统之间互相访问的话他们的域需要一样的        cookie.setDomain("127.0.0.1");        //相应出去        response.addCookie(cookie);        //保存用户的信息        LoginCacheUtil.logionUser.put(token,first.get());    }else {        //登陆失败        session.setAttribute("msg","登陆失败,或是密码错误~~啦啦啦");        return "login";    }    //重定向到target页面中去    //return "redirect:"+target;    return "/seccuss";}

    11.通过token获取用户的信息接口,这里就是判断一下用户是否登陆过

//通过token获取用户的信息的接口,这里也就是来判断用户是否登录共过@GetMapping@ResponseBodypublic ResponseEntitygetUserInfo(String token){    //如果tiken不为空的话,说明已经登陆过了,有信息的话就返回回去    if (!StringUtils.isEmpty(token)){        User user = LoginCacheUtil.logionUser.get(token);        return ResponseEntity.ok(user);    }else {        //为空的话就返回一个错误的请求        return  new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);    }}

    12.为了在视图层跳转的规范,还应该在重定向的方法中加入一个Cookie的参数,这个参数可能有也可能没有:

//跳转到登录页面//@RequestParam(required = false,defaultValue = ""   这个参数可能不存在,就定义为空@GetMapping("/login")public String login(@RequestParam(required = false,defaultValue = "") String target,HttpSession session,@CookieValue(required = false,value="TOKEN") Cookie cookie){    if (StringUtils.isEmpty(target)){        target="http://127.0.0.1:9010";//跳转到首页    }    //cookie不等于null就说明登录过了    if (cookie !=null){        String value = cookie.getValue();//获取到cookie的信息        User user = LoginCacheUtil.logionUser.get(value);//把这个cookie放到用户中去判段是否为空        if (user !=null){            return "/success";        }    }    //这里还是需要做地址的校验的额    session.setAttribute("target",target);//存在session中    return "login";}

在做到这个方案的时候有一个bug卡了我一个小时,必须记录下,在重定向跳转报错

org.thymeleaf.exceptions.TemplateInputException: Error resolving template [r

这里必须在重定向上加:return "redirect:"+返回路径,记得带冒号;

    13.接下来测试,当一个服务的模块登陆成功之后,其他模块点击登录就直接显示登陆成功的页面;

    14.然后继续优化,在main服务中,显示登录的信息,首先在启动类的容器中,这个注入是在调用其他服务的时候需要用到这个@Bean,把它放到SpringMVC中去~

@Beanpublic RestTemplate restTemplate(){    return new RestTemplate();}

    15.然后在用到它的地方注入进来就可以了~~

//注入进来@AutowiredRestTemplate restTemplate;

    16.然后再main的服务中的index重定向方法的参数中加上浏览器中的用户信息,@CookieValue(required = false,value = "TOKEN")解释一下它,这个获取cookie中的信息是必须的,因为在没有登陆的时候就是null,登陆过后就是有用户信息的了~

@CookieValue(required = false,value = "TOKEN") Cookie cookie

    17.需要定义一个静态的访问远程服务的url,这个接口就是login服务中的接口,需要通过刚刚注入进来的restTemplate去获取这个路径

 private final String LOGIN_INFO_TOKEN = "http://127.0.0.1:9000/login/info?token=";

    18.最终如下:

package com.sso.main.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.util.StringUtils;import org.springframework.web.bind.annotation.CookieValue;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.client.RestTemplate;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.util.Map;/** * @Author:dada * @Date:2020/10/31 18:20 * @Version 1.0 */@Controller@RequestMapping("view")public class ViewController {    //注入进来    @Autowired    RestTemplate restTemplate;    private final String LOGIN_INFO_TOKEN = "http://127.0.0.1:9000/login/info?token=";    @GetMapping("/index")    public String index(@CookieValue(required = false,value = "TOKEN") Cookie cookie, HttpSession session){        if (cookie!=null){            String token = cookie.getValue();            if (!StringUtils.isEmpty(token)){                //如果有信息的话去调用9000端口的服务,返回类型最后一个是个Map.class,不能用new Map,这里我们拿到了登录的信息                Map result = restTemplate.getForObject(LOGIN_INFO_TOKEN + token, Map.class);                //拿到信息之后把登录的信息存到session中,保存完之后就去html页面展示吧~~                session.setAttribute("loginUser",result);            }        }        return "/index";    }}

这是一个main的服务模块到这里就结束了,其他模块的代码也跟这个一样了,略微的需要修改一下,最终的效果就是在其中一个模块中登录了,其他的几个服务模块刷新之后就自动登录了~总结原理:就是所有服务模块跑起来之后,在某一个项目中登录了,需要把登陆人的信心保存到cookie中,然后在另几个服务模块中刷新就相当于重新请求后台接口,在请求的时候再次调用cookie里面的信息,根据前面定义的UUID去cookie中查询用户的信息(账号密码),如果存在,就代表已经登录过了,前提需要这些服务的域是一样的,比如我的网站dd16888.cn就都要以这个主域名看齐,不能出现其他的域名~

以上是我的个人笔记,探索未知密宝,记录学习笔记,分享有趣的故事,欢迎大家来访!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值