zoukankan      html  css  js  c++  java
  • Spring Cloud(6.2):搭建OAuth2 Client

    配置web.xml

    添加spring-cloud-starter-security,spring-security-oauth2-autoconfigure和spring-boot-starter-oauth2-client 3个依赖。

    <!-- Spring cloud starter: Security -->
    <!-- Include: web, actuator, security, zuul, etc. -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-security</artifactId>
    </dependency>
    <!-- Spring Security OAuth2 Autoconfigure (optional in spring-cloud-security after 2.1) -->
    <dependency>
        <groupId>org.springframework.security.oauth.boot</groupId>
        <artifactId>spring-security-oauth2-autoconfigure</artifactId>
    </dependency>
    <!-- Spring Security OAuth2 Client (optional in spring-cloud-security after 2.1) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>

    此外,它还是一个Eureka Client和Config Client,如何配置Eureka Client和Config Client请看前面章节。

     

    配置Application

    添加@EnableOAuth2Client注解,声明为OAuth2 Client。

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

    SSO单点登录的配置

    (1)配置Configer

    该服务作为一个OAuth2 Client,可以使用上一节的OAuth2 Server来登录。这其实就是SSO单点登录的例子。

    package com.mycloud.demo.config;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
    import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
    import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
    import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
    import org.springframework.security.oauth2.core.user.OAuth2User;
    
    @Configuration
    public class AppSqlConfiger2 extends WebSecurityConfigurerAdapter {
    
        /* (non-Javadoc)
        * @see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(org.springframework.security.config.annotation.web.builders.HttpSecurity)
        */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
    
            //@formatter:off
            http.authorizeRequests()
                    .antMatchers("/", "/index**", "/login**", "/error**").permitAll()
                    .antMatchers("/sql-sp-search/**").hasRole("SQL_USER")
                    .antMatchers("/sql-tr-search/**").hasRole("SQL_USER")
                .and().logout().logoutSuccessUrl("/")
                .and().oauth2Login().userInfoEndpoint().userService(userService())
            ;
            //@formatter:on
        }
    
        @SuppressWarnings("unchecked")
        private OAuth2UserService<OAuth2UserRequest, OAuth2User> userService() {
    
            //@formatter:off
            // Why configure this?
            // The default user-authority is DefaultOAuth2UserService.java, OAuth2UserAuthority.java and DefaultOAuth2User.java.
            // But the authority is set to ROLE_USER instead of authorities come from user-info endpoint on OAuth2UserAuthority.
            // So we need to reset the authority again after 'DefaultOAuth2UserService.loadUser()'.
            //@formatter:on
            final OAuth2UserService<OAuth2UserRequest, OAuth2User> delegate = new DefaultOAuth2UserService();
            return (userRequest) -> {
                OAuth2User oauthUser = delegate.loadUser(userRequest);
    
                List<GrantedAuthority> authorities = new ArrayList<>();
                Object obj = oauthUser.getAttributes().get("authorities");
                if (obj != null) {
                    List<String> authoritiesStrList = (List<String>) obj;
                    for (String elem : authoritiesStrList) {
                        GrantedAuthority authority = new SimpleGrantedAuthority(elem);
                        authorities.add(authority);
                    }
                }
    
                return new DefaultOAuth2User(authorities, oauthUser.getAttributes(), "user");
            };
        }
    }

    [注1] 我们在这里使用了oauth2Login()及自定义了一个OAuth2UserService。OAuth2UserService实际上就是上一节中讲的调用Authorization Server的/user端点拿到的User信息。至于为什么自定义了一个OAuth2UserService,可以看代码中的注释。

    (2)配置参数

    ## Spring info
    spring:
      # OAuth2 Client info (see ClientRegistration.java) 
      security:
        oauth2:
          client:
            registration:
              server-auth:
                client-id: app-sql-client
                client-secret: '{cipher}e93cce4a8056a7359ded238e97a1c6d25142e6b688873a1e6181ac06753dd9ae'
                # basic or post (default is basic)
                # client-authentication-method: basic
                # authorizationGrantType cannot be null, authorizationGrantType must be authorization_code
                authorization-grant-type: authorization_code
                # redirectUriTemplate cannot be empty, default is '{baseUrl}/login/oauth2/code/{registrationId}'
                redirect-uri: http://localhost:10200/app-sql/login/oauth2/code/server-auth
                scope: all
                # client-name: app-sql
            provider:
              server-auth:
                # It's very important to add 'scope=all' to the url. Auth Server didn't config the scope, so in client side,
                # we must config it, otherwise, 'Empty scope (either the client or the user is not allowed the requested scopes)'
                # error occurred.
                # use zuul to replace 'http://localhost:10030/server-auth/xxx'
                token-uri: http://localhost:10020/server-zuul/s3/server-auth/oauth/token?scope=all
                authorization-uri: http://localhost:10020/server-zuul/s3/server-auth/oauth/authorize
                user-info-uri: http://localhost:10020/server-zuul/s3/server-auth/user
                # header, form or query (default is header)
                # user-info-authentication-method: header
                # the key used to get the user's "name"
                user-name-attribute: user

    使用OAuth2RestTemplate在Client端调用被OAuth2保护的Resource

    上面几步实际上是搭建一个SSO登录系统,但是如果我们想要在OAuth2 Client端调用OAuth2 Resource时,就需要做一些额外配置了。OAuth2 Resource的配置会在下一节详细介绍,这里主要来讲在OAuth2 Client端如何配置。

    在OAuth2 Client端配置的核心就是OAuth2RestTemplate。我们通过给OAuth2RestTemplate配置好所有访问OAuth2 Authorization Server的参数创建OAuth2RestTemplate,接下来对OAuth2 Resource的调用交给OAuth2RestTemplate即可。

    这里使用password模式为例。

    (1)配置Configer

    @Configuration
    public class AppSqlConfiger {
    
        @Bean
        @ConfigurationProperties("app-sql.resources.app-db")
        protected OAuth2ProtectedResourceDetails resource() {
            return new ResourceOwnerPasswordResourceDetails();
        }
    
        @Bean
        public OAuth2RestTemplate restTemplate() {
            AccessTokenRequest atr = new DefaultAccessTokenRequest();
            return new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(atr));
        }
    }

    (2)配置参数

    ## Regard 'app-sql' as oauth2-client and 'app-db' as oauth2-resource.
    ## Create OAuth2RestTemplate in 'app-sql' and set parameters(see AppSqlConfiger.java) and call 'app-db'.
    app-sql:
      resources:
        app-db:
          clientId: app-sql-client
          clientSecret: '{cipher}e93cce4a8056a7359ded238e97a1c6d25142e6b688873a1e6181ac06753dd9ae'
          grantType: password
          # use zuul to replace 'http://localhost:10030/server-auth/xxx'
          accessTokenUri: http://localhost:10020/server-zuul/s3/server-auth/oauth/token
          scope: all
          username: '{cipher}18a05787c976397d4d7d090ad326cc7417122109f590d8a8ba80cfa35f7a15c3'
          password: '{cipher}ab3894c202393761b8f789dd9f047e116b2008ae98b5f8119030796f905471d8'

    再看Discovery Client

    在Eureka Client一节中,我们讲了使用discoveryClient和loadBalancer来发现服务。现在,我们可以通过zuul来调用其他服务,和loadBalancer类似:

    ServiceInstance instance = loadBalancer.choose("server-zuul");
    String path = String.format("http://%s:%s/server-zuul/a2/app-db/structure-search/app/MORT/env/%s/db/%s/name/%s", instance.getHost(), instance.getPort(), env, db, name);
    ResponseEntity<String> response = restTemplate.exchange(path, HttpMethod.GET, null, String.class);
  • 相关阅读:
    linux权限补充:rwt rwT rws rwS 特殊权限
    关于Linux操作系统下文件特殊权限的解释
    Java学习笔记——Java程序运行超时后退出或进行其他操作的实现
    Java实现 蓝桥杯 算法提高 判断名次
    Java实现 蓝桥杯 算法提高 判断名次
    Java实现 蓝桥杯 算法提高 日期计算
    Java实现 蓝桥杯 算法提高 日期计算
    Java实现 蓝桥杯 算法提高 概率计算
    Java实现 蓝桥杯 算法提高 概率计算
    Java实现 蓝桥杯 算法提高 复数四则运算
  • 原文地址:https://www.cnblogs.com/storml/p/11246104.html
Copyright © 2011-2022 走看看