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);
  • 相关阅读:
    Idea debug报错Command line is too long
    云计算与虚拟化入门通识
    yield from语法
    python中 os._exit() 和 sys.exit(), exit(0)和exit(1) 的用法和区别
    python模块中sys.argv[]使用
    SQLAlchemy中Model.query和session.query(Model)的区别
    MAN VGEXTEND
    Python---基础---dict和set
    Python---基础---元组
    Python---基础---list(列表)
  • 原文地址:https://www.cnblogs.com/storml/p/11246104.html
Copyright © 2011-2022 走看看