一、前言
距离之前写的有2年了,在工作中也实践了不少,之前引入的依赖变成了spring-security-oauth2-autoconfigure和spring-security-oauth2-jose,选取的还是比较新的版本springboot2.6.4 和springcloud2021.0.1
二、auth server
pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.wenx</groupId>
<artifactId>auth-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wenx.oauth</groupId>
<artifactId>au-oauth</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>au-oauth</name>
<description>au-oauth</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.wenx</groupId>
<artifactId>au-domain</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</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.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.4.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.4.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
</project>
auth config
@Slf4j
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Resource
private DataSource dataSource;
/**
* 注入authenticationManager
* 来支持 password grant type
*/
@Resource
private AuthenticationManager authenticationManager;
@Resource
private LettuceConnectionFactory lettuceConnectionFactory;
@Resource
private AuUserDetailsService userDetailsService;
@PostConstruct
public void postConstruct() {
log.debug("[Authorization Server in component oauth] Auto Configure.");
}
/**
* 配置客户端详情服务(ClientDetailsService)
* 客户端详情信息在这里进行初始化
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(jdbcClientDetailsService());
}
/**
* 配置令牌端点(Token Endpoint)的安全约束
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
.tokenKeyAccess("isAuthenticated()")
.checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients();
}
/**
* config
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.authenticationManager(authenticationManager)
// 授权允许存储方式
.approvalStore(createApprovalStore())
// 授权码模式code存储方式
.authorizationCodeServices(createAuthorizationCodeServices())
// token存储方式
.tokenStore(createTokenStore())
.userDetailsService(userDetailsService)
.accessTokenConverter(defaultAccessTokenConverter());
// 自定义确认授权页面
endpoints.pathMapping("/oauth/confirm_access", "/oauth/confirm_access");
// 自定义错误页
endpoints.pathMapping("/oauth/error", "/oauth/error");
}
/**
* 声明 TokenStore 管理方式实现
*
* @return TokenStore
*/
@Bean
public TokenStore createTokenStore() {
return new RedisTokenStore(lettuceConnectionFactory);
}
/**
* 授权store。主要用于Authorization Code模式中,确认授权范围页面。
*
* @return ApprovalStore
*/
@Bean
public ApprovalStore createApprovalStore() {
TokenApprovalStore tokenApprovalStore = new TokenApprovalStore();
tokenApprovalStore.setTokenStore(createTokenStore());
return tokenApprovalStore;
}
/**
* 授权码
*
* @return AuthorizationCodeServices
*/
@Bean
public AuthorizationCodeServices createAuthorizationCodeServices() {
return new JdbcAuthorizationCodeServices(dataSource);
}
/**
* ClientDetails
* @return
*/
@Bean
public ClientDetailsService jdbcClientDetailsService(){
return new JdbcClientDetailsService(dataSource);
}
@Bean
public DefaultAccessTokenConverter defaultAccessTokenConverter(){
return new DefaultAccessTokenConverter();
}
}
web config
@Configuration
@EnableWebSecurity
@Order(2)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final Logger log = LoggerFactory.getLogger(WebSecurityConfiguration.class);
@Autowired
private DataSource dataSource;
/**
* {@link AuthorizationServerEndpointsConfiguration#defaultAuthorizationServerTokenServices()}
*/
@PostConstruct
public void postConstruct() {
log.debug("|- Core [Web Security Configurer Adapter] Auto Configure.");
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
return jdbcTokenRepository;
}
/**
* 大体意思就是antMatcher()``是HttpSecurity的一个方法,他只告诉了Spring我只配置了一个我这个Adapter能处理哪个的url,它与authorizeRequests()没有任何关系。
* <p>
* 然后使用authorizeRequests().antMatchers()是告诉你在antMatchers()中指定的一个或多个路径,比如执行permitAll()或hasRole()。他们在第一个http.antMatcher()匹配时就会生效。
*
* @param http
* @throws Exception
*/
@Override
public void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
// 禁用CSRF 开启跨域
http.csrf().disable().cors();
http.requestMatchers().antMatchers("/oauth/**", "/login**", "/open/**")
.and()
.authorizeRequests()
.antMatchers("/oauth/**").authenticated()
.antMatchers("/open/**").permitAll()
.antMatchers("/actuator/**").permitAll()
.anyRequest().authenticated()
.and().logout().permitAll();
}
}
三、resource server
pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.wenx</groupId>
<artifactId>auth-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wenx</groupId>
<artifactId>auth-user</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>auth-user</name>
<description>auth-user</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.wenx</groupId>
<artifactId>au-domain</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.4.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<!-- javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
resource config
@Configuration
@EnableResourceServer
@Slf4j
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Value("${security.oauth2.client.client-id}")
private String clientId;
@Value("${security.oauth2.resource.id}")
private String resourceId;
@Value("${security.oauth2.client.client-secret}")
private String secret;
@Value("${security.oauth2.resource.token-info-uri}")
private String checkTokenEndpointUrl;
@PostConstruct
public void postConstruct() {
log.debug(" |- Core [Herodotus Resource Server in component oauth] Auto Configure.");
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
// 认证鉴权错误处理,为了统一异常处理。每个资源服务器都应该加上。
resources.resourceId(resourceId).stateless(true);
resources.tokenServices(tokenService());
super.configure(resources);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
// 禁用CSRF 开启跨域
http.csrf().disable().cors();
// @formatter:off
http.authorizeRequests()
.antMatchers("/api/hello").permitAll()
// 指定监控访问权限
.requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
.anyRequest().authenticated();
// 防止iframe 造成跨域
http.headers().frameOptions().disable();
}
@Bean
public RemoteTokenServices tokenService() {
RemoteTokenServices tokenService = new RemoteTokenServices();
tokenService.setClientId(clientId);
tokenService.setClientSecret(secret);
tokenService.setCheckTokenEndpointUrl(checkTokenEndpointUrl);
return tokenService;
}
}
写法的话没太多变化,拓展内容就不写了,demo地址是 https://github.com/wenxpro/auth-gateway
参考项目:https://gitee.com/herodotus/eurynome-cloud
-end-
网友评论