软件编程
位置:首页>> 软件编程>> java编程>> Spring gateway + Oauth2实现单点登录及详细配置

Spring gateway + Oauth2实现单点登录及详细配置

作者:BBinChina  发布时间:2022-12-19 00:16:49 

标签:Spring,gateway,Oauth2,单点登录

场景:

按职能,鉴权系统需要划分 网关(spring gateway) + 鉴权(auth-server)。本文通过实践搭建鉴权系统。

spring gateway

首先引入pom依赖

1、resilience 熔断器
2、gateway 网关
3、eureka client 服务注册中心
4、lombok插件
5、actuator状态监控


<dependencies>
<!--        熔断器-->
       <dependency>
           <groupId>io.github.resilience4j</groupId>
           <artifactId>resilience4j-feign</artifactId>
           <version>1.1.0</version>
       </dependency>

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

<dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
       </dependency>

<!-- Gateway -->
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-gateway</artifactId>
       </dependency>

<!-- 注册中心 -->
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
           <version>2.2.2.RELEASE</version>
       </dependency>

<dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <optional>true</optional>
       </dependency>

<dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-actuator</artifactId>
       </dependency>
</dependencies>

application.yml配置

1、gateway信息
2、actuator状态信息
3、配置eureka server地址及注册信息
4、日志配置
5、获取oauth2的jwt key


server:
 port: 18890
spring:
 application:
   name: open-api-gateway
 profiles:
   active: local
 cloud:
   gateway:
     discovery:
       locator:
         enabled: true
         lower-case-service-id: true
     globalcors:
       corsConfigurations:
         '[/**]':
           allowedOrigins: "*"
           allowedMethods: "*"
     default-filters:
       - AddRequestParameter=gateway_type, member
       - AddRequestHeader=gateway_type, member
management:
 endpoints:
   web:
     exposure:
       include: "*"
 endpoint:
   health:
     show-details: always

eureka:
 instance:
   prefer-ip-address: true
   instance-id: ${spring.cloud.client.ip-address}:${server.port}
 client:
   service-url:
     defaultZone: http://127.0.0.1:22001/eureka
logging:
 level:
   com.dq.edu: debug
   com:
     netflix:
       discovery: error
spring:
 security:
   oauth2:
     resourceserver:
       jwt:
         jwk-set-uri: http://127.0.0.1:18889/auth-server/private/jwk_public_key

gateway 项目目录

Spring gateway + Oauth2实现单点登录及详细配置

核心内容:security配置、PermissionFilter鉴权过滤器

1、security配置


package com.digquant.openapigateway.config;

import com.digquant.openapigateway.entity.Response;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
import org.springframework.security.oauth2.server.resource.web.server.ServerBearerTokenAuthenticationConverter;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.Charset;

@Slf4j
@Configuration
@AllArgsConstructor
@EnableWebFluxSecurity
public class SecurityConfig {

private final ReactiveJwtDecoder jwtDecoder;

@Bean
   public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
       http.cors().disable().csrf().disable();
       http
               .authorizeExchange()
               .pathMatchers("/**").permitAll()
               .pathMatchers("/**/public/**").permitAll()
               .pathMatchers("/**/static/**").permitAll()
               .pathMatchers("/*/oauth/**").permitAll()
               .pathMatchers("/actuator/**").permitAll()
               .pathMatchers(HttpMethod.OPTIONS).permitAll()
               .anyExchange().authenticated()
               .and()
               .exceptionHandling()
               .accessDeniedHandler(serverAccessDeniedHandler())
               .authenticationEntryPoint(serverAuthenticationEntryPoint())
               .and()
               .oauth2ResourceServer()
               .jwt()
               .jwtDecoder(jwtDecoder)
               .and()
               .bearerTokenConverter(new ServerBearerTokenAuthenticationConverter());
       return http.build();
   }

@Bean
   public ServerAccessDeniedHandler serverAccessDeniedHandler() {
       return (exchange, denied) -> {
           log.debug("没有权限");
           String errMsg = StringUtils.hasText(denied.getMessage()) ? denied.getMessage() : "没有权限";
           Response result = new Response(1, errMsg);
           return create(exchange, result);
       };
   }

@Bean
   public ServerAuthenticationEntryPoint serverAuthenticationEntryPoint() {
       return (exchange, e) -> {
           log.debug("认证失败");
           String errMsg = StringUtils.hasText(e.getMessage()) ? e.getMessage() : "认证失败";
           Response result = new Response(1, errMsg);
           return create(exchange, result);
       };
   }

private Mono<Void> create(ServerWebExchange exchange, Response result) {
       return Mono.defer(() -> Mono.just(exchange.getResponse()))
               .flatMap(response -> {
                   response.getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8);
                   DataBufferFactory dataBufferFactory = response.bufferFactory();
                   DataBuffer buffer = dataBufferFactory.wrap(createErrorMsg(result));
                   return response.writeWith(Mono.just(buffer))
                           .doOnError(error -> DataBufferUtils.release(buffer));
               });
   }

private byte[] createErrorMsg(Response result) {
       return result.getErrMsg().getBytes(Charset.defaultCharset());
   }
}

总结:

gateway是基于 WebFlux的响应式编程框架,所以在使用securityConfig时采用的注解是@EnableWebFluxSecurity

2、PermissionFilter


package com.digquant.openapigateway.filter;

import com.digquant.openapigateway.utils.IStrings;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.AbstractOAuth2TokenAuthenticationToken;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

import java.util.Objects;

@Slf4j
@Order
@Component
@AllArgsConstructor
public class PermissionFilter implements WebFilter {

@Override
   public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
       return ReactiveSecurityContextHolder.getContext()
               //排除没有Token的
               .filter(Objects::nonNull)
//                //检查该路径是否需要权限
//                .filter(var -> permissionStore.usingPermission(exchange.getRequest().getPath().value()))
               .map(SecurityContext::getAuthentication)
               .map(authentication -> (JwtAuthenticationToken) authentication)
               .doOnNext(jwtAuthenticationToken -> {
                   String path = exchange.getRequest().getPath().value();
                   log.info("请求 uri {}", path);
               })
               .map(AbstractOAuth2TokenAuthenticationToken::getPrincipal)
               .map(var -> (Jwt) var)
               .map(jwt -> {
                   String tokenValue = jwt.getTokenValue();
                   ServerHttpRequest.Builder builder = exchange.getRequest().mutate();
                   builder.header(HttpHeaders.AUTHORIZATION, IStrings.splice("Bearer ", tokenValue));
                   ServerHttpRequest request = builder.build();
                   return exchange.mutate().request(request).build();
               })
               .defaultIfEmpty(exchange)
               .flatMap(chain::filter);
   }
}

总结
1、使用permissionStore来记录uri的权限要求
2、获取到jwtToken时,处理token所携带的权限,用于匹配是否能请求对应资源

OAuth2 项目目录

Spring gateway + Oauth2实现单点登录及详细配置

pom依赖

1、eureka client
2、spring boot mvc
3、redis 用于存储jwt
4、mysql用于记录用户资源权限
5、oauth2组件
6、httpclient fregn用于用户登陆鉴权


<dependencies>
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
           <version>2.2.2.RELEASE</version>
       </dependency>

<dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>

<dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-data-redis</artifactId>
       </dependency>

<dependency>
           <groupId>org.mybatis.spring.boot</groupId>
           <artifactId>mybatis-spring-boot-starter</artifactId>
           <version>2.1.1</version>
       </dependency>
      <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>druid</artifactId>
           <version>1.1.21</version>
       </dependency>

<dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>8.0.18</version>
       </dependency>

<!--        oauth2-->
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-oauth2</artifactId>
           <version>2.2.0.RELEASE</version>
       </dependency>
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-security</artifactId>
           <version>2.2.0.RELEASE</version>
       </dependency>

<dependency>
           <groupId>org.springframework.security</groupId>
           <artifactId>spring-security-oauth2-jose</artifactId>
           <version>5.2.2.RELEASE</version>
       </dependency>
<!-- HttpClient -->
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-openfeign</artifactId>
           <version>2.2.2.RELEASE</version>
       </dependency>
       <dependency>
           <groupId>io.github.openfeign</groupId>
           <artifactId>feign-okhttp</artifactId>
           <version>10.9</version>
       </dependency>

<dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <optional>true</optional>
       </dependency>

</dependencies>

应用配置


server:
 port: 37766
spring:
 application:
   name: auth-server
 mvc:
   throw-exception-if-no-handler-found: true
 profiles:
   active: dev

mybatis:
 mapper-locations: classpath:mapper/*.xml
 type-aliases-package: com.digquant.enity.po

logging:
 level:
   com:
     digquant:
       dao: info
 file:
   path: /dq/log/new/auth-server

digquant:
 authorization:
   auth-jwt-jks: hq-jwt.jks
   auth-jwt-key: hq-jwt
   auth-jwt-password: hq940313
   access-token-validity-seconds: 14400
   refresh-token-validity-seconds: 86400

1、AuthorizationServerConfig配置


package com.digquant.config;

import com.digquant.dao.CustomRedisTokenStore;
import com.digquant.enity.JWTProperties;
import com.digquant.enity.Response;
import com.digquant.service.OAuthUserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.IOException;

@Slf4j
@Configuration
@AllArgsConstructor
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

private final JWTProperties jwtProperties;

/**
    * 注入权限验证控制器 支持 password grant type
    */
   private final AuthenticationManager authenticationManager;

/**
    * 数据源
    */
   private final DataSource dataSource;

/**
    * 开启refresh_token
    */
   private final OAuthUserService userService;

/**
    * 采用redis 存储token
    */
   private final RedisConnectionFactory redisConnectionFactory;

@Override
   public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
       security.allowFormAuthenticationForClients()
               .checkTokenAccess("permitAll()")
               .tokenKeyAccess("permitAll()")
               .authenticationEntryPoint(authenticationEntryPoint())
               .accessDeniedHandler(accessDeniedHandler());
   }

@Bean
   public AccessDeniedHandler accessDeniedHandler() {
       return (request, response, accessDeniedException) -> {
           Response result = new Response(1, accessDeniedException.getMessage());
           writerResponse(response, result, HttpStatus.FORBIDDEN.value());
       };
   }

@Bean
   public AuthenticationEntryPoint authenticationEntryPoint() {
       return (request, response, authException) -> {
           Response result = new Response(1, authException.getMessage());
           writerResponse(response, result, HttpStatus.UNAUTHORIZED.value());
       };
   }

private void writerResponse(HttpServletResponse response, Response result, int status) throws IOException {
       response.setStatus(status);
       response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
       response.setCharacterEncoding("UTF-8");
       response.getWriter().print(result.getErrMsg());
       response.getWriter().flush();
   }

@Bean("redisTokenStore")
   public TokenStore redisTokenStore() {
       return new CustomRedisTokenStore(redisConnectionFactory);
   }

@Bean
   public JwtAccessTokenConverter jwtAccessTokenConverter() {
       JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
       jwtAccessTokenConverter.setKeyPair(keyStoreKeyFactory().getKeyPair(jwtProperties.getAuthJwtKey()));
       return jwtAccessTokenConverter;
   }

@Bean
   public KeyStoreKeyFactory keyStoreKeyFactory() {
       return new KeyStoreKeyFactory(new ClassPathResource(jwtProperties.getAuthJwtJks()), jwtProperties.getAuthJwtPassword().toCharArray());
   }

@Bean
   public DefaultTokenServices tokenServices() {
       DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
       defaultTokenServices.setTokenStore(redisTokenStore());
       defaultTokenServices.setTokenEnhancer(jwtAccessTokenConverter());
       defaultTokenServices.setSupportRefreshToken(true);
       defaultTokenServices.setReuseRefreshToken(false);
       defaultTokenServices.setAccessTokenValiditySeconds(jwtProperties.getAccessTokenValiditySeconds());
       defaultTokenServices.setRefreshTokenValiditySeconds(jwtProperties.getRefreshTokenValiditySeconds());
       return defaultTokenServices;
   }

@Override
   public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
       //开启密码授权类型
       endpoints
               .authenticationManager(authenticationManager)
               //配置token存储方式
               .tokenStore(redisTokenStore())
               //需要额外配置,用于refres_token
               .userDetailsService(userService)
               //
               .tokenServices(tokenServices())
               .accessTokenConverter(jwtAccessTokenConverter())
               .exceptionTranslator(exceptionTranslator());
   }

@Bean
   public WebResponseExceptionTranslator exceptionTranslator() {
       return exception -> {
           return ResponseEntity.status(HttpStatus.OK).body(new OAuth2Exception(exception.getMessage()));
       };
   }

@Bean
   public ClientDetailsService clientDetails() {
       return new JdbcClientDetailsService(dataSource);
   }

@Override
   public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//        clients.withClientDetails(clientDetails());
       clients.inMemory()
               .withClient("open_api")
               .authorizedGrantTypes("password","refresh_token")
               .authorities("USER")
               .scopes("read", "write")
               .resourceIds("auth-server")
               .secret(new BCryptPasswordEncoder().encode("digquant"));

}
}

2、ResourceServerConfig 资源服务配置


package com.digquant.config;

import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;

@Order(6)
@Configuration
@AllArgsConstructor
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
   private final AccessDeniedHandler accessDeniedHandler;

private final AuthenticationEntryPoint authenticationEntryPoint;

@Override
   public void configure(HttpSecurity http) throws Exception {
       http.csrf().disable();
       http
               .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
               .and().authorizeRequests()
               .antMatchers("/swagger-ui.html","/webjars/**").permitAll()
               .antMatchers("/oauth/**").permitAll()
               .antMatchers("/actuator/**").permitAll()
               .antMatchers("/").permitAll()
               .antMatchers(HttpMethod.OPTIONS).permitAll()
               .anyRequest().permitAll();
   }

@Override
   public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
       resources.authenticationEntryPoint(authenticationEntryPoint)
               .accessDeniedHandler(accessDeniedHandler)
               .resourceId("auth-server");
   }
}

3、SecurityConfig配置


package com.digquant.config;

import com.digquant.service.CustomAuthenticationProvider;
import com.digquant.service.OAuthUserService;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Order(7)
@Configuration
@EnableWebSecurity
@AllArgsConstructor
@AutoConfigureAfter(ResourceServerConfig.class)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

private final OAuthUserService userService;

@Override
   protected void configure(HttpSecurity http) throws Exception {
       http.cors().and().csrf().disable();
       http.authorizeRequests()
               .antMatchers("/oauth/**").permitAll()
               .antMatchers("/public/**").permitAll()
               .antMatchers("/actuator/**").permitAll()
               .antMatchers("/private/**").permitAll()
               .antMatchers("/").permitAll()
               .antMatchers(HttpMethod.OPTIONS).permitAll()
               .anyRequest().permitAll()
               .and()
               .sessionManagement()
               .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
   }

@Override
   public void configure(WebSecurity web) throws Exception {
       web.ignoring().antMatchers("/favor.ico");
   }

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

@Override
   protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       auth.authenticationProvider(authenticationProvider());
   }

@Bean
   public PasswordEncoder passwordEncoder() {
       return new BCryptPasswordEncoder();
   }

@Bean
   public AuthenticationProvider authenticationProvider() {
       CustomAuthenticationProvider provider = new CustomAuthenticationProvider()
               .setUserDetailsService(userService)
               .setPasswordEncoder(passwordEncoder());
       provider.setHideUserNotFoundExceptions(false);
       return provider;
   }

}

4、JwkController 用于gateway 请求jwt私钥


package com.digquant.controller;

import com.digquant.enity.JWTProperties;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
import org.springframework.web.bind.annotation.*;

import java.security.interfaces.RSAPublicKey;
import java.util.Map;

@Api(tags = "jwk")
@RestController
@RequestMapping("/private")
@AllArgsConstructor
public class JwkController {
   private final KeyStoreKeyFactory keyStoreKeyFactory;

private final JWTProperties jwtProperties;

@ApiOperation("获取jwk")
   @PostMapping("/jwk_public_key")
   public Map<String, Object> getKey() {
       RSAPublicKey publicKey = (RSAPublicKey) keyStoreKeyFactory.getKeyPair(jwtProperties.getAuthJwtKey()).getPublic();
       RSAKey key = new RSAKey.Builder(publicKey).build();
       return new JWKSet(key).toJSONObject();
   }

}

注意私钥放到项目的resources目录下

Spring gateway + Oauth2实现单点登录及详细配置

5、用户鉴权服务,获取用户信息


package com.digquant.service;

import com.digquant.enity.to.AuthenticationTO;
import com.digquant.enums.LoginType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class OAuthUserService implements UserDetailsService {

@Autowired(required = false)
   private List<OAuthUserProcessor> oAuthUserProcessors;

public UserDetails loadUser(String username, UsernamePasswordAuthenticationToken authentication) {
       AuthenticationTO authenticationTO = new AuthenticationTO();
       authenticationTO.setUsername(username);
       authenticationTO.setPassword((String) authentication.getCredentials());

Map map = (Map) authentication.getDetails();
       String scope = (String) map.get("scope");
       String grantType = (String) map.get("grant_type");
       String clientId = (String) map.get("client_id");

authenticationTO.setScope(scope);
       authenticationTO.setGrantType(grantType);
       authenticationTO.setLoginType(LoginType.PASSWORD);
       authenticationTO.setClientId(clientId);

if (log.isDebugEnabled()) {
           log.debug("请求认证参数:{}", authenticationTO);
       }
       if (!CollectionUtils.isEmpty(oAuthUserProcessors)) {
           //目前只支持客户端密码登录方式
           for (OAuthUserProcessor oAuthUserProcessor : oAuthUserProcessors) {
               if (oAuthUserProcessor.support(authenticationTO)) {
                   UserDetails userDetails = oAuthUserProcessor.findUser(authenticationTO);
                   //TODO 需要加载OpenApi用户的权限
                   loadAuthorities(userDetails, authenticationTO);
                   return userDetails;
               }
           }
       }
       throw new UsernameNotFoundException("用户不存在");
   }

private void loadAuthorities(UserDetails userDetails, AuthenticationTO authenticationTO) {

}

@Override
   public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
       return null;
   }
}

获取token

Spring gateway + Oauth2实现单点登录及详细配置

refresh_token

Spring gateway + Oauth2实现单点登录及详细配置

来源:https://blog.csdn.net/BBinChina/article/details/120428326

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com