zoukankan      html  css  js  c++  java
  • 服务之间的资源权限校验

    四路:- 这个操作是否应该在网关来做?  服务之间的调用权限还是适合在服务自身处理

    a: 创建拦截器1,用于服务之间的请求校验

    b: 创建拦截器2,用于restTemplate请求的校验

    1- 编写拦截器1

    package spring.cloud.common.interceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
    import com.alibaba.fastjson.JSON;
    import spring.cloud.common.context.UserContextHolder;
    import spring.cloud.common.util.UserPermissionUtil;
    import spring.cloud.common.vo.User;
    
    public class UserContextInterceptor extends HandlerInterceptorAdapter {
    
        private static final Logger log = LoggerFactory.getLogger(UserContextInterceptor.class);
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse respone, Object arg2) throws Exception {
            User user = getUser(request);
            // TODO 日常测试先关闭服务间的资源权限校验
    //        UserPermissionUtil.permission(user);
    //        if(!UserPermissionUtil.verify(user,request)) {
    //            respone.setHeader("Content-Type", "application/json");
    //            String jsonstr = JSON.toJSONString("no permisson access service, please check");
    //            respone.getWriter().write(jsonstr);
    //            respone.getWriter().flush();
    //            respone.getWriter().close();
    //            throw new PermissionException("no permisson access service, please check");
    //        }
            UserContextHolder.set(user);
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse respone, Object arg2, ModelAndView arg3)
                throws Exception {
            // DOING NOTHING
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse respone, Object arg2, Exception arg3)
                throws Exception {
            UserContextHolder.shutdown();
        }
    
        private User getUser(HttpServletRequest request){
            String userid = request.getHeader("x-user-id");
            String username = request.getHeader("x-user-name");
            User user = new User();
            user.setUserId(userid);
            user.setUserName(username);
            return user;
        }
    
        static class PermissionException extends RuntimeException {
            private static final long serialVersionUID = 1L;
            public PermissionException(String msg) {
                super(msg);
            }
        }
    }

    2 - 编写校验工具类

    package spring.cloud.common.util;
    
    import java.util.ArrayList;
    import java.util.List;
    import javax.servlet.http.HttpServletRequest;
    import org.springframework.util.StringUtils;
    import spring.cloud.common.vo.User;
    
    public class UserPermissionUtil {
    
        /**
         * 模拟权限校验, 可以根据自己项目需要定制不同的策略,如查询数据库获取具体的菜单url或者角色等等.
         * @param user
         */
        public static boolean verify(User user, HttpServletRequest request){
            // TODO 从请求头获取用户信息,再查询DB判断该用户是否具有该服务或者该服务下某个url的权限
            String url = request.getHeader("x-user-serviceName");
            if(StringUtils.isEmpty(user)) {
                return false;
            }else {
                List<String> str = user.getAllowPermissionService();
                for (String permissionService : str) {
                    if(url.equalsIgnoreCase(permissionService)) {
                        return true;
                    }
                }
                return false;
            }
        }
    
        /**
         * 模拟权限赋值, 可以根据自己项目需要定制不同的策略,如查询数据库获取具体的菜单url或者角色等等.
         * 该方法应该放到业务层,通过访问DB获取权限资源列表
         * @param user
         */
        public static void permission(User user){
            if(user.getUserName().equals("admin")) {
                List allowPermissionService = new ArrayList();
                // TODO 查询DB资源权限数据
                allowPermissionService.add("client-service");
                allowPermissionService.add("provider-service");
                allowPermissionService.add("SPRING-CLOUD-FEIGN");
                user.setAllowPermissionService(allowPermissionService);
            }else if(user.getUserName().equals("spring")) {
                List allowPermissionService = new ArrayList();
                allowPermissionService.add("client-service");
                user.setAllowPermissionService(allowPermissionService);
            } else {
                List allowPermissionService = new ArrayList();
                user.setAllowPermissionService(allowPermissionService);
            }
        }
    
    }

    3- 编写上下文持有对象

    package spring.cloud.common.context;
    
    import spring.cloud.common.vo.User;
    
    public class UserContextHolder {
        public static ThreadLocal<User> context = new ThreadLocal<>();
        public static User currentUser() {
            return context.get();
        }
        public static void set(User user) {
            context.set(user);
        }
        public static void shutdown() {
            context.remove();
        }
    }

    4- 编写拦截器2

    package spring.cloud.common.interceptor;
    
    import java.io.IOException;
    import org.springframework.http.HttpRequest;
    import org.springframework.http.client.ClientHttpRequestExecution;
    import org.springframework.http.client.ClientHttpRequestInterceptor;
    import org.springframework.http.client.ClientHttpResponse;
    import spring.cloud.common.context.UserContextHolder;
    import spring.cloud.common.vo.User;
    
    public class RestTemplateUserContextInterceptor implements ClientHttpRequestInterceptor {
    
        @Override
        public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
                throws IOException {
            User user = UserContextHolder.currentUser();
            request.getHeaders().add("x-user-id",user.getUserId());
            request.getHeaders().add("x-user-name",user.getUserName());
            request.getHeaders().add("x-user-serviceName",request.getURI().getHost());
            return execution.execute(request, body);
        }
    }

    5 将2个拦截器注入IOC容器

    package spring.cloud.common.config;
    
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    import spring.cloud.common.interceptor.RestTemplateUserContextInterceptor;
    import spring.cloud.common.interceptor.UserContextInterceptor;
    
    /**
     * 详见 https://www.cnblogs.com/duanxz/p/4875153.html
     */
    @Configuration
    @EnableWebMvc
    public class CommonConfiguration implements WebMvcConfigurer {
    
        /**
         * 请求拦截器
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            System.out.println("--------------UserContextInterceptor-------------");
            registry.addInterceptor(new UserContextInterceptor());
            //可以指定拦截器的路劲
            //registry.addInterceptor(new ThemeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
            //registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*");
        }
    
        /***
         * RestTemplate 拦截器,在发送请求前设置鉴权的用户上下文信息
         * @return
         */
        @LoadBalanced
        @Bean
        public RestTemplate restTemplate() {
            System.out.println("--------------resttemplate-------------");
            RestTemplate restTemplate = new RestTemplate();
            restTemplate.getInterceptors().add(new RestTemplateUserContextInterceptor());
            return restTemplate;
        }
    
    }
  • 相关阅读:
    mysql5.7初始化密码报错 ERROR 1820 (HY000): You must reset your password using ALTER USER statement
    Python 国内镜像源
    PyCharm
    MySQL 表字段唯一性约束设置方法unique
    ch01系统基础信息模块详解
    Django出错提示TemplateDoesNotExist at /
    windows更改pip源(可用)
    异常处理
    前端基础学习(4) BOM DOM 节点操作 事件
    前端练习题 1 BOM DOM
  • 原文地址:https://www.cnblogs.com/domi22/p/10524124.html
Copyright © 2011-2022 走看看