【Spring Security】Spring Security Oauth2用户授权及token的传递

【Spring Security】Spring Security Oauth2用户授权及token的传递_第1张图片

前言

上边分享如何实现网关鉴权介绍,那么问题来了,所有用户进来可以是不同的角色,不同的权限,这里后端怎么控制呢。

方法授权

需求分析

方法授权要完成的是provider访问根据jwt令牌完成对方法的授权,具体流程如下:

  1. 生成Jwt令牌时在令牌中写入用户所拥有的权限我们给每个权限起个名字,例如某个用户拥有如下权限:
    batman:访问providerhello接口
  2. hello方法上添加注解PreAuthorize,并指定此方法所需要的权限,它就表示要执行这个方法需要拥有batman权限。hello2表示要拥有batman2权限才能访问。
     @Override
    @PreAuthorize("hasAuthority('batman')")
    public String hello() {
        return "hello world oauth2";
    }

    @Override
    @PreAuthorize("hasAuthority('batman2')")
    public String hello2() {
        return "hello world oauth2";
    }
  1. 当请求有权限的方法时正常访问
  2. 当请求没有权限的方法时则拒绝访问

jwt令牌包含权限

修改provider服务的UserDetailServiceImpl类,下边的代码中 permissionList列表中存放了用户的权限,并且将权限标识按照中间使用逗号分隔的语法组成一个字符串,最终提供给Spring security。(这里将权限写死了,大家可以遵循RABC原则建关系表,从数据库中查询角色权限)

//TODO从数据库获取权限
        List<FooMenu> permissions = userext.getPermissions();
        List<String> user_permission = new ArrayList<>();
        permissions.forEach(item -> user_permission.add(item.getCode()));
        user_permission.add("batman");
        String user_permission_string = StringUtils.join(user_permission.toArray(), ",");

方法授权测试

重启provider服务,使用postman测试,GET 请求 http://batman.com:18085/security-provider/security/hello ,注意加上Authorization

【Spring Security】Spring Security Oauth2用户授权及token的传递_第2张图片

GET 请求http://batman.com:18085/security-provider/security/hello2

【Spring Security】Spring Security Oauth2用户授权及token的传递_第3张图片

小结

  1. ResourceServerConfig类上添加注解,如下:
//激活方法上的PreAuthorize注解
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
  1. 在方法添加授权注解
@PreAuthorize("hasAuthority('???')")
  1. 如果方法上不添加授权注解表示此方法不需要权限即可访问。

服务token传递

定义Feign拦截器

微服务之间使用feign进行远程调用,采用feign拦截器实现远程调用携带JWT。

创建 FeignClientInterceptor

public class FeignClientInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        try {
            //使用RequestContextHolder工具获取request相关变量
            ServletRequestAttributes attributes = (ServletRequestAttributes)
                    RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                //取出request
                HttpServletRequest request = attributes.getRequest();
                Enumeration<String> headerNames = request.getHeaderNames();
                if (headerNames != null) {
                    while (headerNames.hasMoreElements()) {
                        String name = headerNames.nextElement();
                        String values = request.getHeader(name);
                        if (name.equals("authorization")) {
                            //System.out.println("name="+name+"values="+values);
                            requestTemplate.header(name, values);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注入到spring容器

    @Bean
    public FeignClientInterceptor feignClientInterceptor() {
        return new FeignClientInterceptor();
    }

你可能感兴趣的:(spring,cloud,spring,jwt)