使用springsecurity568和springcloudgateway实现一个基于oauth21的统一认证网关
- 引入依赖
在springcloudgateway的pom.xml文件中加入以下依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
- 配置网关
在application.yml中配置网关的路由规则和OAuth2认证信息:
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/users/**
filters:
- RewritePath=/users/(?<remaining>.*), /$\{remaining}
- TokenRelay
- id: product-service
uri: lb://product-service
predicates:
- Path=/products/**
filters:
- RewritePath=/products/(?<remaining>.*), /$\{remaining}
- TokenRelay
- id: auth-service
uri: lb://auth-service
predicates:
- Path=/oauth/**
filters:
- TokenRelay
security:
oauth2:
client:
clientId: web
clientSecret: secret
accessTokenUri: http://localhost:8080/oauth/token
userAuthorizationUri: http://localhost:8080/oauth/authorize
resource:
userInfoUri: http://localhost:8080/user/me
其中,路由规则中的TokenRelay过滤器用于将OAuth2认证信息传递给后端服务。
- 配置安全认证
在SecurityConfig中配置安全认证:
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/oauth/**").permitAll()
.anyRequest().authenticated()
.and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
其中,/oauth/**请求不需要认证,其他请求需要认证。
- 配置资源服务器
在ResourceServerConfig中配置资源服务器:
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/user/**").authenticated()
.anyRequest().permitAll();
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("resource");
}
}
其中,/user/**请求需要认证。
- 配置认证服务器
在AuthorizationServerConfig中配置认证服务器:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private DataSource dataSource;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("web")
.secret(passwordEncoder.encode("secret"))
.authorizedGrantTypes("authorization_code", "refresh_token", "password")
.scopes("read", "write")
.autoApprove(true)
.redirectUris("http://localhost:8081/login/oauth2/code/custom");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService)
.tokenStore(tokenStore());
}
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
其中,配置了一个clientId为web,clientSecret为secret的客户端,并支持授权码、刷新令牌和密码授权模式,授权范围为read和write,重定向URI为http://localhost:8081/login/oauth2/code/custom。
- 配置用户服务
在UserServiceImpl中实现用户服务:
@Service
public class UserServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if ("admin".equals(username)) {
return new User(username, "{bcrypt}$2a$10$8t4M4tOcZ1lXZtqnzF0b7Ojg36yTbTJ0l0CJQ80/JEE6Z89FL9ZC", new ArrayList<>());
}
return null;
}
}
其中,密码为123456,经过BCryptPasswordEncoder加密后的值为$2a$10$8t4M4tOcZ1lXZtqnzF0b7Ojg36yTbTJ0l0CJQ80/JEE6Z89FL9ZC。
- 测试
启动认证服务器、用户服务、产品服务和网关,并使用浏览器访问http://localhost:8080/oauth/authorize?client_id=web&response_type=code&scope=read&redirect_uri=http://localhost:8081/login/oauth2/code/custom,登录后返回code。
使用curl获取access_token:
curl -X POST \
http://localhost:8080/oauth/token \
-H 'Authorization: Basic d2ViOnNlY3JldA==' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code&code=XTjKtJ&redirect_uri=http://localhost:8081/login/oauth2/code/custom'
使用curl访问受保护资源:
curl -X GET \
http://localhost:8080/user/me \
-H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiIsImF1ZCI6IndlYiIsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9vYXV0aC90b2tlbiIsImV4cCI6MTY0ODg3MjI1OSwiaWF0IjoxNjQ4ODc5NjU5LCJqdGkiOiI1MjI2MTUxYi03ZjM5LTQxZDAtOWMzZi1jZmQ2ODA0YmQwMTMifQ.B6jSTU6e8u6p47z9XmBn5nBv7r5rWtdiHqd3wJcgsxvF8cjWmIY9l3qz3jSvP8lKJ4yR7Gwrd0x0fjJt4BPZ0sXO-1cZJvzF8jKfTbABMw_WBQxJxKjGgkNGfZ3q3nE7SgGJ8tMfRgJnAUV4m4t4BmG9XZn1zLlLajZCpKc35XYNXXCwGyT1A2QsT8E9ZzY6OjG1d2QkW8B6ykdD1jwU6eKU6W8u9gY5P5o5v7iH1W8xr1qgQHA3q3vFv5W5h5R9DZzg5ZMv5aW1u8ju1Qyq3wCnVa5GTFZY5dNzZ56c6Zj7v2QW6N8gVUJj6wL7JUxWpLlJZgGc1zJdZIomA0z8GyCJL-2FQ1Q'
如果access_token有效,则返回用户信息。如果access_token无效,则返回401错误。
原文地址: https://www.cveoy.top/t/topic/b1zN 著作权归作者所有。请勿转载和采集!