zoukankan      html  css  js  c++  java
  • Spring cloud微服务安全实战-3-5 API安全机制之认证(2)

    基于Http协议的认证方式有很多。本节我们只讲一个最简单的HttpBasic认证。聪明就可以看出来,这是一个最基础的认证,好处是简单方便,所有的主流浏览器都支持,问题就是并不是非常安全的,但是帮我们大家理解认证这个概念是足够的。

    首先要对认证信息做Base64的加密,加密之前要把这两个信息组合起来。用户名冒号密码组合成这样一个字符串。然后拿这个字符串做Base64的字符串的加密。并生成一个字符串。

    把生成的串放到http请求的 请求头里面。带个前缀 Basic +空格 + 加密后的字符串。

    开始写代码


    先加上字符串处理的工具的引用。commons-lang3这里面有个字符串处理的工具类

    <dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    </dependency>


    建一个新的过滤器BaseicAuthecationFilter

    继承OncePerRequestFilter


    @Component声明称一个组件,这样SpringBoot会自动把他加到应用的过滤器链上。

    注入UserRepository



    用java.util这个包下的也可以,用Base64Utils这个也可以。

    根据冒号拆分成两个字符串

    创建这个根据UserName查询的方法



    之前写的findByName删掉。

    User findByUsername(String username);


    StringUtils用的都是apache.commons.lang3这个包下的类。

    package com.imooc.security.filter;
    
    import com.imooc.security.user.User;
    import com.imooc.security.user.UserRepository;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.util.Base64Utils;
    import org.springframework.web.filter.OncePerRequestFilter;
    
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @Component
    public class BasicAuthecationFilter extends OncePerRequestFilter {
    
        @Autowired
        private UserRepository userRepository;
    
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
            String authHeader = request.getHeader("Authorization");
            if(StringUtils.isNotBlank(authHeader)){
                String token64 = StringUtils.substringAfter(authHeader, "Basic ");
                String token = new String(Base64Utils.decodeFromString(token64));//解码
                //根据冒号拆分成两个字符串
                String[] items = StringUtils.splitByWholeSeparatorPreserveAllTokens(token, ":");
                String username = items[0];
                String password = items[1];
                User user = userRepository.findByUsername(username);
                if(user!=null && StringUtils.equals(password,user.getPassword())){
                    request.setAttribute("user",user);
                }
            }
            filterChain.doFilter(request,response);
        }
    }
    Filter代码



    因为我们还没有写审计等的代码,这里我们先在controller里面写代码,先看到效果。
    user里面getId获取到id和当前的接口传递过来的参数id对象,如果不相等就抛出异常。

    遇到的错误

    出现问题的原因

    修改成Long即可

    继续


    在User实体类里面。写一个方法,buildInfo,。把User对象转换成UserInfo对象。

    
    
    public UserInfo buildInfo(){
    UserInfo info=new UserInfo();
    BeanUtils.copyProperties(this,info);
    return info;
    }
     


    JPA提供的findById默认的返回类型是一个Optional的类型。

    UserServiceImpl 。所以要先get()再调用buildInfo()

     public UserInfo get(Long id) {
            return userRepository.findById(id).get().buildInfo();
        }

    运行测试

    现在在请求头里面根本没有带认证信息。这里是个get请求。查询id为1的用户信息

    {
        "timestamp": "2019-12-10T09:05:46.377+0000",
        "status": 500,
        "error": "Internal Server Error",
        "message": "身份认证信息异常,获取用户信息失败",
        "path": "/users/1"
    }


    在过滤器里面,相当于这一段完全没有执行

    经过过滤器会进入到controller里面。在Arttribute里面拿到的是空。所以就抛出了异常。

       @GetMapping("/{id}")
        public UserInfo get(@PathVariable Long id, HttpServletRequest request){
            User user=(User) request.getAttribute("user");
    
    
            if(user == null || !user.getId().equals(id)) {
                throw new RuntimeException("身份认证信息异常,获取用户信息失败");
            }
            return userService.get(id);
        }







    发出去的完整的信息里面已经带了请求头的信息了。但是 依然报了异常

    这是因为创建的用户的id是5 但是回去的用户信息id是1。所以造成了id的不匹配。

    把请求的id改成5


    这样用户信息成功返回

    以上就是认证起作用的一个简单的例子。
     

    postman里面的设置

     

    结束

     

  • 相关阅读:
    HDU5418.Victor and World(状压DP)
    POJ2686 Traveling by Stagecoach(状压DP)
    POJ3254Corn Fields(状压DP)
    HDU5407.CRB and Candies(数论)
    CodeForces 352D. Jeff and Furik
    CodeForces 352C. Jeff and Rounding(贪心)
    LightOj 1282 Leading and Trailing
    Ural 1057. Amount of Degrees(数位DP)
    HDU 2089 不要62 (数位DP)
    HDU5366 The mook jong (DP)
  • 原文地址:https://www.cnblogs.com/wangjunwei/p/11903806.html
Copyright © 2011-2022 走看看