maven引用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
配置授权服务器
这里需要注意的是配置token的参数:
其中【withClient】和【secret】中配置的参数在后面获取access_token时需要用到。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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;
/**
* 配置授权服务器,认证服务配置
*/
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
/**
* 注入authenticationManager
* 来支持 password grant type
*/
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
/**
* 配置开启验证
* 授权服务安全配置
*
* @param oauthServer
* @throws Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
/**
* 对于端点可以匿名访问
* [/oauth/authorize] [/oauth/token] [/oauth/check_token]
* [/oauth/confirm_access] [/oauth/token_key] [/oauth/error]
*/
// 开启该配置,才可以使用oauth2认证,否则模式默认是HTTP的基本认证
oauthServer.allowFormAuthenticationForClients();
//这两个配置,目的是开启两个端点url
oauthServer
//url:/oauth/token_key,exposes public key for token verification if using JWT tokens
.tokenKeyAccess("permitAll()")
//url:/oauth/check_token allow check token
.checkTokenAccess("isAuthenticated()");
}
/**
* 配置token的参数
*
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client")
.secret("{noop}secret")
.authorizedGrantTypes("password", "authorization_code", "client_credentials", "implicit", "refresh_token")
.scopes("all")
.resourceIds("resourcesId")
.accessTokenValiditySeconds(1200)
.refreshTokenValiditySeconds(50000);
}
/**
* 配置token的类型 密码模式
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager).allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
endpoints.userDetailsService(userDetailsService);
}
}
配置资源服务器
主要配置哪些url需要做oauth验证
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
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;
/**
* 配置资源服务器
* 配置oauth2的链路Filter
*/
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
/**
* 配置那些url要做oauth验证
* @param http
* @throws Exception
*/
@Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/v1/**").and().authorizeRequests().antMatchers("/v1/**").authenticated();
// 禁用 session
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests().anyRequest().authenticated().and()
.cors().and()
.csrf().disable();
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
// 配置资源 ID
resources.resourceId("resourcesId").stateless(true);
}
}
配置安全
其中UserDetailsService配置用户名和密码。
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
/**
* 配置安全
*/
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class WebConfig extends WebSecurityConfigurerAdapter {
/**
* 过滤那些url需要验证。模式是需要HTTP BASIC认证
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.requestMatchers().antMatchers("/oauth/**")
.and()
.authorizeRequests()
.antMatchers("/oauth/**").authenticated();
}
/**
* 必须注入 AuthenticationManager,不然oauth无法处理四种授权方式
* 即:需要配置这个支持password模式 support password grant type
* @return
* @throws Exception
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
AuthenticationManager manager = super.authenticationManagerBean();
return manager;
}
/**
* 注入UserDetailsService
* @return
*/
@Bean
@Override
protected UserDetailsService userDetailsService() {
InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager();
userDetailsManager.createUser(User.withUsername("sed").password("{noop}sed123").authorities("USER").build());
return userDetailsManager;
}
}
创建测试方法
如下图所示。创建两个测试方法,一个做oauth验证,一个不做oauth验证:
启动项目。
测试结果
1、首先测试获取token的方法:
其中【grant_type】表示密码模式,固定值为【password】,另外四个参数则是配置而来。
2、测试不做oauth验证的接口
3、测试oauth验证的接口
直接访问会报错【Full authentication is required to access this resource】:
报错的原因是需要获取accesstoken,参数加上前面获取到的token则可以访问成功: