zoukankan      html  css  js  c++  java
  • OAuth2.0协议专区-SpringCloud+zuul+oauth2 实现服务统一认证

    第一种配置方式:zuul只负责转发,流控等(不负责认证)

    1.介绍

    (1) eureka服务发现,各服务配置就不发了,只看关于认证这块;

    2 配置认证服务器

    (1)添加依赖(oauth已经包含了security)

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

    (2)配置认证

    @Configuration
    public class MyConfig {
     
        //设置用户信息处理类,这里为了测试使用密码123,用户名随意
        @Component
        public static class MyUserDetailsService implements UserDetailsService {
            
         @Autowired private PasswordEncoder passwordEncoder; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { return new User(username, passwordEncoder.encode("123"), AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); } } //认证服务器 @EnableAuthorizationServer @Configuration public static class Authorization extends AuthorizationServerConfigurerAdapter { @Autowired AuthenticationManager authenticationManager; @Autowired BCryptPasswordEncoder bCryptPasswordEncoder; @Autowired MyUserDetailsService myUserDetailsService; //为了测试客户端与凭证存储在内存(生产应该用数据库来存储,oauth有标准数据库模板) @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("client") // client_id .secret(bCryptPasswordEncoder.encode("123")) // client_secret .authorizedGrantTypes("authorization_code", "password") // 该client允许的授权类型 .scopes("app"); // 允许的授权范围 } //authenticationManager配合password模式使用,tokenstore生产可用redis @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager) .tokenStore(new InMemoryTokenStore()) .userDetailsService(myUserDetailsService); } //配置token状态查询 @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security.tokenKeyAccess("permitAll()"); security.checkTokenAccess("isAuthenticated()"); } } //认证服务器需配合Security使用 @Configuration public static class SecurityConfig extends WebSecurityConfigurerAdapter {
         @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } //这里只验证是否带有token的失败返回authenticationEntryPoint @Override protected void configure(HttpSecurity http) throws Exception {   http.httpBasic().and() .csrf().disable() .exceptionHandling() .authenticationEntryPoint((req, resp, exception) -> { resp.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); resp.getWriter().write(new ObjectMapper().writeValueAsString(new HashMap() {{ put("status", 0); put("error", "没有权限"); }})); }).and() .authorizeRequests().anyRequest().authenticated(); } } //配置资源处理器,为了其他客户端访问该登陆用户信息等 @Configuration @EnableResourceServer public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.csrf().disable().exceptionHandling().authenticationEntryPoint((req, resp, exception) -> { resp.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); resp.getWriter().write(new ObjectMapper().writeValueAsString(new HashMap() {{ put("status", 0); put("error", "没有权限"); }})); }).and().authorizeRequests().anyRequest().authenticated(); } } }

      

    (3)提供客户信息

    @RestController
    public class ResourceWeb {
     
        @GetMapping("/member")
        public Principal user(Principal member) {
            //获取当前用户信息
            return member;
        }
    }

    (4)流程

      这里用的是密码方式,一般用于本地服务自身资源的调用;

    (client,secret)代表客户端账号密码,在该测试中,这个客户端其实就表示本地的服务.如果是第三方,则申请到账号密码后,可以在得到用户授权后进行资源调用;

    (username,password)就是本服务的用户主体了,所有客户端获取资源都需要本地用户的登陆成功授权后方可获取,所以用到了security的登陆策略;

    3.配置资源服务器(本地资源)

    (1)同样添加oauth依赖

    (2)配置远程认证服务:

    security:
      oauth2:
        resource:
          user-info-uri: http://localhost:8082/member
          prefer-token-info: false
    

      

    @Configuration
    public class MyConfig {
     
        //配置资源服务器
        @Configuration
        @EnableResourceServer
        public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
            @Override
            public void configure(HttpSecurity http) throws Exception {
                http.csrf().disable().httpBasic().disable().exceptionHandling().authenticationEntryPoint((req, resp, exception) -> {
                    resp.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
                    resp.getWriter().write(new ObjectMapper().writeValueAsString(new HashMap() {{
                        put("status", 0);
                        put("error", "没有权限");
                    }}));
                })
                .and().authorizeRequests().antMatchers("/noauth").permitAll()
                .and().authorizeRequests().anyRequest().authenticated();
            }
        }
    }
    

    4.配置zuul

    zuul:
      #routes:
      #  MECHANT:
      #    service-id: MECHANT
      #    path: /mechant/**
      strip-prefix: true    #当为false时,请求地址->MECHANT->http://localhost:8081/api/mechant/ping,返回404
      prefix: /api          #请求前缀
      sensitive-headers:   #此处不写则无法携带header;如果客户端在发请求是带了X-ABC,那么X-ABC不会传递给下游服务
      #ignoredHeaders: X-ABC    #如果客户端在发请求是带了X-ABC,那么X-ABC依然会传递给下游服务。但是如果下游服务再转发就会被过滤
    

      

    5.测试

    (1)申请token(使用zuul访问)

    (2)使用token(使用zuul访问)

  • 相关阅读:
    题目3:爬楼梯
    题目1:删除排序数组中的重复数字
    最近目标
    软件工程----个人总结
    软件工程第二次作业——结对编程
    软件工程第一次作业补充
    爬楼梯
    买卖股票的最佳时机
    删除排序数组中的重复数字
    思考题
  • 原文地址:https://www.cnblogs.com/liboware/p/12528755.html
Copyright © 2011-2022 走看看