SpringCloud--zuul和oauth2

版权声明:商业用途请联系博主,非商业转载请标明出处。 https://blog.csdn.net/qq_15807167/article/details/82729310

此篇我将介绍 将zuul 层 和 oauth2 进行分别作为两个服务处理。

zuul

进行路由分发和进行关联oauth2服务

  • Pom需要的依赖
		 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
  • 配置文件
server:
  port: 10000
  servlet:
    session:
      cookie:
        name: UISESSION
spring:
  cloud:
    consul:
      host: localhost
      #  Consul监听端口8500
      port: 8500
      discovery:
        # 配置服务注册到Consul上
        register: true
        # 配置服务健康检测地址  供Consul 调用
        health-check-path: /api/health
        # consul 健康检测频率
        health-check-interval: 15s
        # 配置注册到consul 服务的id
        instance-id: ${spring.application.name}:${server.port}
        enabled: true
        service-name: ${spring.application.name}
  application:
    name: ecology-getway
  thymeleaf:
    cache: true
zuul:
  host:
    connect-timeout-millis: 10000
    socket-timeout-millis: 60000
  routes:
    ratelimit-api:
      path: /ratelimit-api/**
      serviceId: service-client
      sensitiveHeaders: "*"
    login:
      path: /login/**
      sensitiveHeaders: "*"
      serviceId: server-login
    auth:
      path: /uaa/**
      serviceId: ecology-oauth2
      strip-prefix: true
      custom-sensitive-headers: true
    user:
      path: /user/**
      serviceId: service-account-center
  ratelimit:
    key-prefix: ratelimit-api
    # 启动限流服务
    enabled: true
    behind-proxy: true
    default-policy:
      # 请求数量
      limit: 100
      # 请求总时间
      quota: 20
      # 统计窗口刷新时间
      refresh-interval: 60
      # 限流类型
      type: url
  ignored-services: '*'
  add-proxy-headers: true
  retryable: true
  sensitive-headers:
security:
  oauth2:
    client:
      access-token-uri: http://localhost:${server.port}/uaa/oauth/token
      user-authorization-uri: http://localhost:${server.port}/uaa/oauth/authorize
      client-id: open-api
    resource:
      user-info-uri: http://localhost:${server.port}/uaa/user
      prefer-token-info: false
  • springboot入口处进行配置 开启zuul
@EnableZuulProxy
@SpringBootApplication
@EnableDiscoveryClient
  • 增加我们的websecurity的配置
@Configuration
@EnableWebSecurity
@Order(SecurityProperties.BASIC_AUTH_ORDER - 3)
class SecurityConfig : WebSecurityConfigurerAdapter() {

    override fun configure(http: HttpSecurity?) {
        http!!
                .csrf()
                .disable()
    }


}

oauth2

Oauth2的服务模块

资源配置

根据自己的情况进行修改,是否部分资源可以不需要授权进行请求

@Configuration
@EnableResourceServer
class ResourceServerConfig : ResourceServerConfigurerAdapter(){

    override fun configure(http: HttpSecurity?) {
        http!!
                .anonymous()
                .disable()
                .requestMatchers()
                .antMatchers("/api/**")
                .and()
                .authorizeRequests()
                .antMatchers("/api/**")
                .fullyAuthenticated()
                .and()
                .exceptionHandling()
                .accessDeniedHandler(OAuth2AccessDeniedHandler())
    }
}

授权服务

这里采用了redis进行Token的存储。

@Configuration
@EnableAuthorizationServer
class AuthorizationServerConfig : AuthorizationServerConfigurerAdapter(){

    @Autowired
    private lateinit var oAuth2DatabaseClientDetailsService: OAuth2DatabaseClientDetailsService

    @Autowired
    private lateinit var authenticationManager: AuthenticationManager

    @Autowired
    private lateinit var redisFactory: RedisConnectionFactory

    @Bean
    fun tokenStore(): TokenStore {
       return RedisTokenStore(redisFactory)
    }

    override fun configure(security: AuthorizationServerSecurityConfigurer?) {
        security!!
                .tokenKeyAccess("permitAll()")
    }

    override fun configure(clients: ClientDetailsServiceConfigurer?) {
        clients!!.withClientDetails(oAuth2DatabaseClientDetailsService)
    }

    override fun configure(endpoints: AuthorizationServerEndpointsConfigurer?) {
        endpoints!!
                .authenticationManager(authenticationManager)
                .tokenStore(tokenStore())
    }
}

web策略

@Configuration
class WebSecurityConfig : WebSecurityConfigurerAdapter(){

    private var log: Logger = LoggerFactory.getLogger(WebSecurityConfig::class.java)

    @Bean
    fun userDetail():UserDetailsService {
        return DataBaseUserDetailsService()
    }


    @Bean
    fun passwordEncoder(): PasswordEncoder {
        return BCryptPasswordEncoder()
    }

    override fun configure(auth: AuthenticationManagerBuilder?) {
        auth!!
                .userDetailsService(userDetail())
                .passwordEncoder(passwordEncoder())
    }

    @Bean
    override fun authenticationManagerBean(): AuthenticationManager {
        return super.authenticationManagerBean()
    }


    override fun configure(http: HttpSecurity?) {
        http!!
                .authorizeRequests()
                .antMatchers("/", "/auth/**", "/api/health", "/oauth/**", "/default/**", "/login","/user")
                .permitAll()
                .anyRequest()
                .authenticated()
    }

    override fun configure(web: WebSecurity?) {
        web!!.ignoring().antMatchers("/resources/**")
    }

    /**
     * describe: 返回对应的用户名
     * author 候帅
     * date 2018/8/19 上午9:28
     * @return 用户名
     */
    @Bean
    fun auditorAwareBean(): String {
        val authentication = SecurityContextHolder.getContext().authentication
        if (authentication == null || AuthenticationTrustResolverImpl().isAnonymous(authentication))
            return "@SYSTEM"
        val principal = authentication.principal
        return when (principal) {
            is String -> principal
            is UserDetails -> principal.username
            else -> principal.toString()
        }
    }
}

用户UserDetails服务


/**
 * FileName: DataBaseUserDetailsService
 * author:   候帅
 * data:     18/08/2018 07:40
 * Description: 自定义用户身份获取
 * History:
 */
@Service
class DataBaseUserDetailsService :UserDetailsService {

    private val log: Logger = LoggerFactory.getLogger(DataBaseUserDetailsService::class.java)

    companion object {
        private const val ROLE_PREFIX: String = "ROLE_"
    }

    @Autowired
    private lateinit var userFeign: UserFeign

    @Autowired
    private lateinit var accessTokenRepository: AccessTokenRepository

    @Autowired
    private lateinit var clientDetailsRepository: ClientDetailsRepository

    override fun loadUserByUsername(username: String?): UserDetails {

       return Optional.ofNullable(userFeign.findUserInfo(username!!))
                .map {
                    return@map User(it.account, it.password, it.roles.stream()
                            .map {
                                return@map SimpleGrantedAuthority(prefixRoleName(it))
                            }
                            .collect(Collectors.toList()))
                }.orElseThrow {
                    return@orElseThrow UsernameNotFoundException("User $username was not found in the database")
                }
    }

    /**
     * describe: 获取客户端的Token 内容
     * author 候帅
     * date 2018/8/18 下午10:21
     * @param tokenId token对应的id
     * @return   返回间隔时间
     */
    fun loadClientByToken(tokenId: String): Triple<Long, String, Long> {
        val clientId = accessTokenRepository
                .findOneByTokenId(tokenId)
                .map { return@map it.clientId }
                .orElseThrow {
                    return@orElseThrow UsernameNotFoundException("Token $tokenId was not found in the database")
                }
        val details = clientDetailsRepository.findOneByClientId(clientId).get()
        val clientLimit = details.clientLimit
        return Triple(clientLimit.intervalInMills, clientId, clientLimit.limits)
    }

    /**
     * describe: 将未有前缀的内容 添加
     * author 候帅
     * date 2018/8/18 下午10:20
     * @param roleName 角色名
     * @return 返回过滤的角色名
     */
    fun prefixRoleName(roleName: String): String {
        if (!StringUtils.isEmpty(roleName) && !roleName.startsWith(ROLE_PREFIX))
            return ROLE_PREFIX + roleName
        return roleName
    }
}

配置文件

server:
  port: 10010
spring:
  cloud:
    consul:
      host: localhost
      #  Consul监听端口8500
      port: 8500
      discovery:
        # 配置服务注册到Consul上
        register: true
        # 配置服务健康检测地址  供Consul 调用
        health-check-path: /api/health
        # consul 健康检测频率
        health-check-interval: 15s
        # 配置注册到consul 服务的id
        instance-id: ${spring.application.name}:${server.port}
        enabled: true
        service-name: ${spring.application.name}
  application:
    name: ecology-oauth2
  redis:
    # 设置数据库索引
    database: 0
    host: localhost
    port: 6379
    password:
    jedis:
      pool:
        max-active: 10
        max-idle: 10
        min-idle: 0
        max-wait: -1ms
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/andy?useSSL=false
    username: root
    password: root
    dbcp2:
      # 初始化连接数
      initial-size: 5
      # 最小连接数
      min-idle: 5
      # 最大连接数
      max-idle: 20
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
  profiles:
    include: default-user-and-roles_route
ribbon:
  eager-load:
    enabled: false


猜你喜欢

转载自blog.csdn.net/qq_15807167/article/details/82729310