十.SpringCloud+Security+Oauth2实现微服务授权-环境准备

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: SpringCloud+Security+Oauth2实现微服务授权-环境准备

1.概述

1.1.SpringSecurity-Oauth2介绍

SpingSecurityOauth2实现了Oatuh2,SpingSecurityOauth2分为两个大块,一者为认证授权(Authorization Server)服务和资源服务(Resource server),认证授权服务一般负责执行认证逻辑(登录)和加载用户的权限(给用户授权),以及认证成功后的令牌颁发 ,而资源服务器一般指的是我们系统中的微服务(被访问的微服务),在资源服务器需要对用户的令牌(认证成功与否),以及授权(是不是有访问权限)做检查 。

1.2.微服务Oauth2认证解决方案

这里我们需要准备四个服务,1.授权服务 2.资源服务,3.网关,4注册中心,一共4个服务。授权服务和资源服务的流程图:

image.png

请求流程是:

  • 浏览器向认证服务提交认证获取Token
  • 浏览器存储Token并向资源服务器发起请求
  • 资源服务器校验Token并对资源进行授权

2.微服务环境准备

注意:没有SpringCloud基础的同学先去学SpringCloud,搭建基本项目结构如下

security-parent  //父工程
    security-auth-server  //统一认证微服务
    security-eureka-server  //注册中心
    security-resource-server  //资源微服务
    security-zuul-server  //网关
2.1.搭建父工程

管理SpringBoot和SpringCloud相关依赖,管理公共依赖,以及依赖版本统一管理

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.5.RELEASE</version>
</parent>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Finchley.SR1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
2.2搭建EurekaServer注册中心

1.导入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

2.启动类

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
   
   

    public static void main(String[] args) {
   
   
        SpringApplication.run(EurekaServerApplication.class);
    }
}

3.yml配置

server:
  port: 1000
eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false #禁用注册中心向自己注册
    fetchRegistry: false  #不让注册中心获取服务的注册列表
    serviceUrl:
      defaultZone: http://localhost:1000/eureka/
      #注册中心的注册地址 ,其他微服务需要向这个地址注册
2.3.搭建ZuulServer网关微服务

微服务统一访问入口,后面实现统一鉴权操作。
1.导入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
</dependencies>

2.启动类

@SpringBootApplication
@EnableZuulProxy
public class EurekaServerApplication {
   
   

    public static void main(String[] args) {
   
   
        SpringApplication.run(EurekaServerApplication.class);
    }
}

3.yml配置

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:1000/eureka/ #注册中心地址
  instance:
    prefer-ip-address: true #使用ip地址注册
    instance-id: zuul-server:2000  #指定服务的id
server:
  port: 2000
zuul:
  ignored-services: "*"   #禁止使用服务名字进行访问
  prefix: "/servers"  #统一的前缀
  routes: #配置路由,指定服务的访问路径
    resource1-server: "/resources/**"
spring:
  application:
    name: zuul-server
2.4.搭建AuthServer认证授权微服务

认证微服务,实现认证逻辑,用户授权,令牌颁发等
1.导入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

2.启动类

@SpringBootApplication
public class AuthServerApplication {
   
   
    public static void main(String[] args) {
   
   
        SpringApplication.run(AuthServerApplication.class) ;
    }
}

3.yml配置

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:1000/eureka/ #注册中心地址
  instance:
    prefer-ip-address: true #使用ip地址注册
    instance-id: auth-server:3000  #指定服务的id
server:
  port: 3000
spring:
  application:
    name: auth-server
2.5.搭建Resource1Server资源微服务

资源服务,负责校验Token和资源授权
1.导入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

2.启动类

@SpringBootApplication
public class Resource1ServerApplication {
   
   
    public static void main(String[] args) {
   
   
        SpringApplication.run(Resource1ServerApplication.class) ;
    }
}

3.yml配置

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:1000/eureka/ #注册中心地址
  instance:
    prefer-ip-address: true #使用ip地址注册
    instance-id: resource1-server:4000  #指定服务的id
server:
  port: 4000
spring:
  application:
    name: resource1-server

启动测试http://localhost:1000/

image.png

3.认证服务配置

3.1.创建相关组件

修改security-auth-server服务,完成User,Role,Permission实体类的创建,以及mapper映射器,Mapper.xml等相关组件的创建 , 以及相关表的创建和关系维护,这里省略...

3.2.集成MyBatis

1.security-auth-server增加依赖,"spring-cloud-starter-oauth2"包含了Oauth2和Security的内容

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-oauth2</artifactId>
    </dependency>

        <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.20</version>
    </dependency>
    <!-- mysql 数据库驱动. -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>1.1.1</version>
    </dependency>
</dependencies>

2.开启Mapper扫描"MapperScan"

@SpringBootApplication
@MapperScan("cn.itsource.mapper")
public class AuthServerApplication {
   
   

    public static void main(String[] args) {
   
   
        SpringApplication.run(AuthServerApplication.class) ;
    }
}

3.yml增加DataSource和MyBatis配置

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:1000/eureka/ #注册中心地址
  instance:
    prefer-ip-address: true #使用ip地址注册
    instance-id: auth-server:3000  #指定服务的id
server:
  port: 3000
mybatis:
  mapper-locations: classpath:cn/itsource/mapper/*Mapper.xml
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    username: root
    password: admin
    url: jdbc:mysql:///auth-rbac
    driver-class-name: com.mysql.jdbc.Driver
  application:
    name: auth-server
3.3.配置UserDetailsService

定义一个类,实现UserDetailsService接口,复写loadUserByUsername,根据用户名从数据库中获取认证的用户对象,并且加载用户的权限信息,把用户的认证信息和权限信息封装成UserDetaials返回。
在前面的章节已经学习过UserDetailsService的配置这里不在赘述配置如下

package cn.itsource.userdetails;

import cn.itsource.domain.Permission;
import cn.itsource.domain.User;
import cn.itsource.mapper.PermissionMapper;
import cn.itsource.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Component
public class UserDetailServiceImpl implements UserDetailsService {
   
   

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    /**
     * 加载数据库中的认证的用户的信息:用户名,密码,用户的权限列表
     * @param username: 该方法把username传入进来,
        我们通过username查询用户的信息(密码,权限列表等)
        然后封装成 UserDetails进行返回 ,交给security 。
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
   
   
        //User是security内部的对象,UserDetails的实现类 ,
        //用来封装用户的基本信息(用户名,密码,权限列表)
        //public User(String username, String password, Collection<? extends GrantedAuthority> authorities)


        User userFromDB = userMapper.selectByUsername(username);
        if(null == userFromDB){
   
   
            throw new RuntimeException("无效的用户");
        }

        //模拟存储在数据库的用户的密码:123
        //String password = passwordEncoder.encode("123");
        String password = userFromDB.getPassword();

        //查询用户的权限
        List<Permission> permission = permissionMapper.selectPermissionsByUserId(userFromDB.getId());

        //用户的权限列表,暂时为空
        Collection<GrantedAuthority> authorities = new ArrayList<>();
        permission.forEach(e->{
   
   
            System.out.println("用户:"+userFromDB.getUsername()+" 加载权限:"+e.getExpression());
            authorities.add(new SimpleGrantedAuthority(e.getExpression()));
        });
        //注意:这里的User是Security的User不是我们自己的User
        org.springframework.security.core.userdetails.User  user = new org.springframework.security.core.userdetails.User (username,password, authorities);

        return user;
    }
}

认证服务在处理认证逻辑的时候会通过该userDetailService加载用户在数据库中的认证信息实现身份认证,同时在整个方法中也加载了用户的权限列表,后续当用户发起对资源服务的访问时,是否能够授权成功就跟用户的权限列表息息相关了。

3.4.配置Security

在前面的章节已经学习过WebSecurity的配置这里不在赘述,配置如下

//Security配置
@Configuration
@EnableWebSecurity(debug = false)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
   
   

    //密码 编码器
    @Bean
    public PasswordEncoder passwordEncoder(){
   
   
        return new BCryptPasswordEncoder();
    }

    //授权规则配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
   
   

        http.csrf().disable()   //屏蔽跨域防护
                .authorizeRequests()          //对请求做授权处理
                .antMatchers("/login").permitAll()  //登录路径放行
                .anyRequest().authenticated() //其他路径都要拦截
                .and().formLogin()  //允许表单登录, 设置登陆页
                .and().logout().permitAll();    //登出
    }

    //配置认证管理器,授权模式为“poassword”时会用到

    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
   
   
        return super.authenticationManager();
    }

}

这里多配置了一个AuthenticationManager 认证管理器,配置它的目录是后续Oauth2支持password模式需要做认证时会用到认证管理器

配置到这里已经完成了一个简单的认证流程了,测试访问:http://localhost:3000/login 应该可以完成一个简单的认证流程

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
19天前
|
JSON Java API
利用Spring Cloud Gateway Predicate优化微服务路由策略
Spring Cloud Gateway 的路由配置中,`predicates`​(断言)用于定义哪些请求应该匹配特定的路由规则。 断言是Gateway在进行路由时,根据具体的请求信息如请求路径、请求方法、请求参数等进行匹配的规则。当一个请求的信息符合断言设置的条件时,Gateway就会将该请求路由到对应的服务上。
124 69
利用Spring Cloud Gateway Predicate优化微服务路由策略
|
3天前
|
搜索推荐 NoSQL Java
微服务架构设计与实践:用Spring Cloud实现抖音的推荐系统
本文基于Spring Cloud实现了一个简化的抖音推荐系统,涵盖用户行为管理、视频资源管理、个性化推荐和实时数据处理四大核心功能。通过Eureka进行服务注册与发现,使用Feign实现服务间调用,并借助Redis缓存用户画像,Kafka传递用户行为数据。文章详细介绍了项目搭建、服务创建及配置过程,包括用户服务、视频服务、推荐服务和数据处理服务的开发步骤。最后,通过业务测试验证了系统的功能,并引入Resilience4j实现服务降级,确保系统在部分服务故障时仍能正常运行。此示例旨在帮助读者理解微服务架构的设计思路与实践方法。
43 16
|
6天前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
22天前
|
Java 关系型数据库 Nacos
微服务SpringCloud链路追踪之Micrometer+Zipkin
SpringCloud+Openfeign远程调用,并用Mircrometer+Zipkin进行链路追踪
180 20
|
11天前
|
Java 关系型数据库 数据库
微服务SpringCloud分布式事务之Seata
SpringCloud+SpringCloudAlibaba的Seata实现分布式事务,步骤超详细,附带视频教程
32 1
|
2月前
|
设计模式 Java API
微服务架构演变与架构设计深度解析
【11月更文挑战第14天】在当今的IT行业中,微服务架构已经成为构建大型、复杂系统的重要范式。本文将从微服务架构的背景、业务场景、功能点、底层原理、实战、设计模式等多个方面进行深度解析,并结合京东电商的案例,探讨微服务架构在实际应用中的实施与效果。
154 6
|
2月前
|
设计模式 Java API
微服务架构演变与架构设计深度解析
【11月更文挑战第14天】在当今的IT行业中,微服务架构已经成为构建大型、复杂系统的重要范式。本文将从微服务架构的背景、业务场景、功能点、底层原理、实战、设计模式等多个方面进行深度解析,并结合京东电商的案例,探讨微服务架构在实际应用中的实施与效果。
61 1
|
1月前
|
Java 开发者 微服务
从单体到微服务:如何借助 Spring Cloud 实现架构转型
**Spring Cloud** 是一套基于 Spring 框架的**微服务架构解决方案**,它提供了一系列的工具和组件,帮助开发者快速构建分布式系统,尤其是微服务架构。
191 69
从单体到微服务:如何借助 Spring Cloud 实现架构转型
|
1月前
|
运维 监控 持续交付
微服务架构解析:跨越传统架构的技术革命
微服务架构(Microservices Architecture)是一种软件架构风格,它将一个大型的单体应用拆分为多个小而独立的服务,每个服务都可以独立开发、部署和扩展。
244 36
微服务架构解析:跨越传统架构的技术革命
|
4月前
|
安全 应用服务中间件 API
微服务分布式系统架构之zookeeper与dubbo-2
微服务分布式系统架构之zookeeper与dubbo-2