spring security webflux 单点登录

论坛 期权论坛 脚本     
已经匿名di用户   2022-3-21 23:58   2414   0

spring security webflux 单点登录

webflux作为客户端使用授权中心进行登录认证,授权认证功能交由授权中心集中处理

***********************

认证服务器:authorization-service

*****************

配置文件

application.yml

spring:
  application:
    name: authorization-service

server:
  port: 8081

*****************

service 层

UserService

@Service
public class UserService implements UserDetailsService {

    @Resource
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        String name="gtlx";
        String password=passwordEncoder.encode("123456");
        String role="admin";

        List<SimpleGrantedAuthority> list=new ArrayList<>();
        list.add(new SimpleGrantedAuthority(role));

        return new User(name,password,list);
    }
}

*****************

config 层

WebSecurityConfig

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public BCryptPasswordEncoder initPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin().and().authorizeRequests()
                .antMatchers("/**").permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("gtlx")
                .password(initPasswordEncoder().encode("123456"))
                .authorities("admin");
    }
}

OAuth2AuthorizationServerConfiguration

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private BCryptPasswordEncoder passwordEncoder;

    @Resource
    private UserService userService;

    @Resource
    private CustomUserAuthenticationConverter customUserAuthenticationConverter;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer authorizationServerEndpointsConfigurer) throws Exception {
        DefaultAccessTokenConverter defaultAccessTokenConverter=new DefaultAccessTokenConverter();
        defaultAccessTokenConverter.setUserTokenConverter(customUserAuthenticationConverter);

        authorizationServerEndpointsConfigurer
                .tokenStore(initTokenStore())
                .authenticationManager(authenticationManager)
                .accessTokenConverter(defaultAccessTokenConverter)
                .userDetailsService(userService);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().withClient("user")
                .secret(passwordEncoder.encode("123456"))
                .authorizedGrantTypes("authorization_code","refresh_token")
                .redirectUris("http://localhost:8082/login/oauth2/code/custom")
                .accessTokenValiditySeconds(3000)
                .autoApprove(true)
                .scopes("user");
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients()
                .tokenKeyAccess("isAuthenticated()")    //获取token
                .checkTokenAccess("isAuthenticated()"); //验证token
    }

    @Bean
    public TokenStore initTokenStore(){
        return new InMemoryTokenStore();
    }
}

*****************

controller 层

HelloController

@RestController
public class HelloController {

    @Resource
    private TokenStore tokenStore;

    @RequestMapping("/user")
    public Principal getUser(String access_token){
        Authentication authentication=tokenStore.readAuthentication(access_token).getUserAuthentication();
        System.out.println("userAuthentication:"+userAuthentication);

        return authentication;
    }

    @RequestMapping("/")
    public String redirect(){
        return "redirect";
    }
}

***********************

客户端:webflux

*****************

配置文件

application.yml

spring:
  security:
    oauth2:
      client:
        registration:
          custom:
            provider: custom
            client-id: user
            client-secret: 123456
            authorization-grant-type: authorization_code
            redirect-uri: "{baseUrl}/login/oauth2/code/custom"
            client-name: gitee
            scope: user
        provider:
          custom:
            authorization-uri: http://localhost:8081/oauth/authorize
            token-uri: http://localhost:8081/oauth/token
            user-info-uri: http://localhost:8081/user

server:
  port: 8082

*****************

config 层

CustomReactiveAccessTokenResponseClient

@Component
public class CustomReactiveOAuth2AccessTokenResponseClient implements ReactiveOAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> {

    @Override
    public Mono<OAuth2AccessTokenResponse> getTokenResponse(OAuth2AuthorizationCodeGrantRequest oAuth2AuthorizationCodeGrantRequest) {
        ClientRegistration clientRegistration=oAuth2AuthorizationCodeGrantRequest.getClientRegistration();

        return Mono.defer(() -> WebClient.create().post().uri(clientRegistration.getProviderDetails().getTokenUri(),new Object[0])
                .body(createRequestBody(oAuth2AuthorizationCodeGrantRequest))
                .exchange().flatMap(response -> response.body(OAuth2BodyExtractors.oauth2AccessTokenResponse()))
        );
    }

    private BodyInserters.FormInserter<String> createRequestBody(OAuth2AuthorizationCodeGrantRequest oAuth2AuthorizationCodeGrantRequest){
        ClientRegistration clientRegistration=oAuth2AuthorizationCodeGrantRequest.getClientRegistration();

        return BodyInserters.fromFormData("grant_type","authorization_code")
                .with("client_id",clientRegistration.getClientId())
                .with("client_secret",clientRegistration.getClientSecret())
                .with("redirect_uri",oAuth2AuthorizationCodeGrantRequest.getAuthorizationExchange().getAuthorizationRequest().getRedirectUri())
                .with("code", oAuth2AuthorizationCodeGrantRequest.getAuthorizationExchange().getAuthorizationResponse().getCode());
    }
}

CustomReactiveOAuth2UserService

@Service
public class CustomReactiveOAuth2UserService implements ReactiveOAuth2UserService<OAuth2UserRequest, OAuth2User> {

    @Override
    public Mono<OAuth2User> loadUser(OAuth2UserRequest oAuth2UserRequest) throws OAuth2AuthenticationException {
        ParameterizedTypeReference<Map<String,Object>> parameterizedTypeReference= new ParameterizedTypeReference<Map<String,Object>>() {};

        String uri=oAuth2UserRequest.getClientRegistration().getProviderDetails()
                .getUserInfoEndpoint().getUri()+"?access_token={access_token}";

        Map<String,String> params=new HashMap<>();
        params.put("access_token",oAuth2UserRequest.getAccessToken().getTokenValue());

        Mono<Map<String, Object>> userAttributes = WebClient.create().get().uri(uri,params)
                .retrieve().bodyToMono(parameterizedTypeReference);

        return userAttributes.map(attrs ->{
            Set<GrantedAuthority> authorities=new HashSet<>();
            authorities.add(new SimpleGrantedAuthority("ROLE_USER"));

            return new DefaultOAuth2User(authorities,attrs,"name");
        });
    }
}

WebSecurityConfig

@Configuration
public class WebSecurityConfig {
 
    @Resource
    private CustomReactiveOAuth2AccessTokenResponseClient oAuth2AccessTokenResponseClient;
 
    @Resource
    private CustomReactiveOAuth2UserService oAuth2UserService;
 
    @Bean
    public SecurityWebFilterChain initSecurityWebFilterChain(ServerHttpSecurity http){
 
        http.oauth2Login().and().authorizeExchange()
                .pathMatchers("/hello2").hasRole("USER")
                .pathMatchers("/**").permitAll();
 
        http.oauth2Login().authenticationManager(new OAuth2LoginReactiveAuthenticationManager(oAuth2AccessTokenResponseClient,oAuth2UserService));
 
        return http.build();
    }
}

*****************

controller 层

HelloController

@RestController
public class HelloController {

    @RequestMapping("/hello2")
    public String hello(Principal principal){
        System.out.println(principal);

        return "hello "+principal.getName();
    }

}

***********************

使用测试

localhost:8082/hello2

认证通过后,输出:hello gtlx

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP