<返回更多

跟常用框架SpringSecurity比 微服务到底胜在哪?

2020-08-28    
加入收藏

前言

JAVA下常用的安全框架主要有Spring Security和shiro,都可提供非常强大的功能,但学习成本较高。在微服务下鉴权多多少少都会对服务有一定的入侵性。 为了降低依赖,减少入侵,让鉴权功能相对应用服务透明,我们采用网关拦截资源请求的方式进行鉴权。

一、整体架构

跟常用框架SpringSecurity比 微服务到底胜在哪?

 


整体结构

用户鉴权模块位于API GateWay服务中,所有的API资源请求都需要从此通过。

  1. 身份认证,通过则缓存用户权限数据,不通过返回401
  2. 用户鉴权,比对当前访问资源(URI和Method)是否在已缓存的用户权限数据中,在则转发请求给对应应用服务,不在则返回403

二、实现步骤

跟常用框架SpringSecurity比 微服务到底胜在哪?

 


登陆鉴权流程

1. 用户登陆

public LoginUser login(String userName, String password){
    // 检查密码
    User user = userService.checkUser(userName, password);    LoginUser loginUser = LoginUser.builder()            .userName(userName)            .realName(user.getRealName())            .userToken(UUID.randomUUID().toString())            .loginTime(new Date())
            .build();    // 保存session
    session.saveSession(loginUser);    // 查询权限
    List<Permission> permissions = permissionRepository.findByUserName(userName);    // 保存用户权限到缓存中
    session.saveUserPermissions(userName, permissions);    return loginUser;
}// ...
// 缓存用户权限到redis
public void saveUserPermissions(String userName, List<Permission> permissions) {    String key = String.format("login:permission:%s", userName);
    HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();    hashOperations.putAll(key, permissions.stream().collect(            Collectors.toMap(p -> p.getMethod().concat(":").concat(p.getUri()),
                    Permission::getName, (k1, k2) -> k2)));
    if (expireTime != null) {
        redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);    }}

2. 拦截请求

@Slf4j
@Component
public class AuthorizationFilter extends AbstractGatewayFilterFactory {
    @Autowired
    private Session session;
    @Override
    public GatewayFilter Apply(Object config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();            ServerHttpResponse response = exchange.getResponse();            String uri = request.getURI().getPath();            String method = request.getMethodValue();            // 1.从AuthenticationFilter中获取userName
            String key = "X-User-Name";
            if (!request.getHeaders().containsKey(key)) {
                response.setStatusCode(HttpStatus.FORBIDDEN);
                return response.setComplete();
            }
            String userName = Objects.requireNonNull(request.getHeaders().get(key)).get(0);
            // 2.验证权限
            if (!session.checkPermissions(userName, uri, method)) {
                log.info("用户:{}, 没有权限", userName);
                response.setStatusCode(HttpStatus.FORBIDDEN);
                return response.setComplete();
            }
            return chain.filter(exchange);
        };
    }
}
public boolean checkPermissions(String userName, String uri, String method) {
    String key = String.format("login:permission:%s", userName);
    String hashKey = String.format("%s:%s", method, uri);
    if (redisTemplate.opsForHash().hasKey(key, hashKey)){
        return  true;
    }    String allKey = "login:permission:all";
    // 权限列表中没有则通过
    return !redisTemplate.opsForHash().hasKey(allKey, hashKey);
}

3. 鉴权Filter配置

spring:
  cloud:
    gateway:
      routes:
        - id: cloud-user
          uri: lb://cloud-user  # 后端服务名
          predicates:
            - Path=/user/**   # 路由地址
          filters:
            - name: AuthenticationFilter  # 身份认证
            - name: AuthorizationFilter   # 用户鉴权
            - StripPrefix=1 # 去掉前缀

三、其它问题

在做单元测试时,如遇到如下错误

nested exception is java.lang.NoClassDefFoundError: javax/validation/ValidationException

请升级依赖包版本:

<!--升级validation-api的版本-->
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.5.Final</version>
</dependency>
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.1.Final</version>
</dependency>

四、完整代码

gitee.com/hypier/barr…

 

最后

大家看完有什么不懂的可以在下方留言讨论.

谢谢你的观看。

觉得文章对你有帮助的话记得关注我点个赞支持一下!

链接:https://juejin.im/post/6865580470151675918

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>