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
|