zoukankan      html  css  js  c++  java
  • Spring cloud微服务安全实战-3-13重构代码

    让代码同时支持两种方式,登陆访问和带着请求头的token访问也可以。

    首先做代码的重构

    这里改成getSession() 改成这样以后会有一个问题,我用httpBasic登陆成功以后,我的用户信息放在session里面,后续的请求不用带Authorization的请求头也能访问。
    我希望实现的效果是,如果你没登陆,那么你用HttpBasic这种方式来访问,每次你的头里面都要带着这个。然后除非你登陆了,访问的时候才可以不带这个头。那么要达到这个效果的话,我们需要来分辨下,哪些session是通过httpBasic这种方式建立的session。
    像下面的这个getSesison就是通过httpBasic这种方式建立的。

    还有一种是调用登陆方法,在登陆方法里面创建的session

    想到达的效果就是,在httpBasic这种方式创建出来的session,在他方法调用结束以后,返回的时候把这个session销毁掉。
    那么下次他再上来的时候session就没了。他就必须手里带着一个token,才能再啦访问这个请求。
    那么要达到这个效果,就是在这里写个try finally

    把过滤器的调用放在try里面。把过滤器的调用放在try里面。然后在finally里面让他失效掉。

    这么写还有个问题就是登陆的那块的session也会失效掉。所以我需要做一个判断。在httpBasic的session中多加一个temp的session。判断它不为空, 就让session失效掉。

    这样我们现在即支持登陆来访问也支持httpBasic访问


    用UserInfo去接收

    这里获取session里面的user改用UserInfo去接收了。那么存session的地方也要存成UserInfo这个类。、存的时候调用user.buildInfo()方法,转换成UserInfo对象即可。



    原来在user写的方法要挪一下


    把这段代码剪切到UserInfo里面




    把这个属性也复制过去,注意是复制,不是剪切。

    SecurityConfig

    之前这里是写死的,现在我明确知道我要从session里面拿用户信息

    那么Spring有一种静态的方法,可以让我们拿到session

    强制转换。




    从serveltRequestAttribute我们就可以拿到当前的request,再从request里拿到session


    现在这个AuditorWare就可以根据真正的用户是谁,就可以拿到它的用户名来并返回。最终审计日志的时候,是当前登陆的用户名了。。

    
    
    @Bean
    public AuditorAware<String> auditorAware(){
    return new AuditorAware<String>() {
    @Override
    public Optional<String> getCurrentAuditor() {
    ServletRequestAttributes servletRequestAttributes=(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
    UserInfo info=(UserInfo)servletRequestAttributes.getRequest().getSession().getAttribute("user");
    String username=null;
    if(info!=null){
    username=info.getUsername();
    }
    //return Optional.of("jojo");
    return Optional.ofNullable(username);
    }
    };
    }
     


    以上就重构完成了。

    做退出操作

    让session失效。UserController里面增加一个logout的方法

    @GetMapping("/logout")
    public void logout(HttpServletRequest request){
    request.getSession().invalidate();//sessin失效
    }


    然后这里也改成UserInfo

    
    
    @GetMapping("/{id}")
    public UserInfo get(@PathVariable Long id, HttpServletRequest request) throws Exception {
    UserInfo user=(UserInfo) request.getAttribute("user");

    if(user == null || !user.getId().equals(id)) {
    throw new RuntimeException("身份认证信息异常,获取用户信息失败");
    }
    return userService.get(id);
    }
     


    修正自己代码的两处问题

    一是在登陆的时候,UserController里面 往session存UserInfo对象的时候,写错了。这里之前是取的user对象,然后存的时候也是存user。 后面存的时候我自己忘了改了。 后来跟了下代码 发现是这里的问题。

    二是在退出登陆的时候,要把退出的请求路径加入到排除列表里面。这样可以直接访问到logout,然后清空session。

    运行系统

    filter里面没有明显的是哪些代码是请求进来的时候调用,哪些代码是响应回去的时候调用,这样看起来不直观,不如拦截器的方法

    拦截器的preHandler和afterCompletion看起来直观。 


    现在是没带请求头也没登陆过。直接访问users/13 所以返回的是401

    http://localhost:8080/users/13



    带上我们的请求头

    带上请求头就拿到用户信息了。


    把请求头删掉依然不能访问,说明httpBasic每次请求响应回去session都被清除了。

    测试登陆




    登陆成功后,不带请求头访问我们的方法,因为我们是登陆过的,服务器端存了session

    调用一下退出的方法

    退出后,再调用getUser方法


    以上就实现了我们想要的效果,我们这个方法支持两种认证方式。方法过程中有流控、身份认证、有审计、有授权等等
    所有的安全机制应该都已经具备了。、

    结束

  • 相关阅读:
    体温单时间控件
    搭建Android 开发环境(精华)
    即时通讯
    车牌识别系统
    JSON 生成 C# Model
    Arduino 视频教程
    .Net主线程扑捉子线程中的异常
    用C#操作IIS创建虚拟目录和网站
    C#中简单的this与get的用法(string,decimal)
    c#读取Excel数据到Gridview
  • 原文地址:https://www.cnblogs.com/wangjunwei/p/11930488.html
Copyright © 2011-2022 走看看