在这段代码中,为了代码简洁,我就不把SpringSecurity用户存到数据库中去了,直接存在内存中。
创建AuthorizationServer类继承自AuthorizationServerConfigurerAdapter,来对授权服务器做进一步的详细配置,AuthorizationServer类记得加上@EnableAuthorizationServer注解,表示开启授权服务器的自动化配置。在AuthorizationServer类中,我们其实主要重写三个configure方法。AuthorizationServerSecurityConfigurer用来配置令牌端点的安全约束,也就是这个端点谁能访问,谁不能访问。ClientDetailsServiceConfigurer用来配置客户端的详细信息,在之前文章中,松哥和大家讲过,授权服务器要做两方面的检验,一方面是校验客户端,另一方面则是校验用户,校验用户,我们前面已经配置了,这里就是配置校验客户端。客户端的信息我们可以存在数据库中,这其实也是比较容易的,和用户信息存到数据库中类似,但是这里为了简化代码,我还是将客户端信息存在内存中,这里我们分别配置了客户端的id,secret、资源id、授权类型、授权范围以及重定向uri。授权类型我在之前文章中和大家一共讲了四种,四种之中不包含refresh_股票交易编程自动接口,token这种类型,但是在实际操作中,refresh_股票交易编程自动接口,token也被算作一种。AuthorizationServerEndpointsConfigurer这里用来配置令牌的访问端点和令牌服务。股票交易编程自动接口,tokenServices这个Bean主要用来配置Token的一些基本信息,例如Token是否支持刷新、Token的存储位置、Token的有效期以及刷新Token的有效期等等。Token有效期这个好理解,刷新Token的有效期我说一下,当Token快要过期的时候,我们需要获取一个新的Token,在获取新的Token时候,需要有一个凭证信息,这个凭证信息不是旧的Token,而是另外一个refresh_股票交易编程自动接口,token,这个refresh_股票交易编程自动接口,token也是有有效期的。
首先通过@EnableSwagger2注解启用Swagger配置一个DocketBean,这个Bean中,配置映射路径和要扫描的接口的位置。在apiInfo中,主要配置一下Swagger2文档网站的信息,例如网站的title,网站的描述,联系人的信息,使用的协议等等。通过securitySchemes来配置全局参数,这里的配置是一个名为Authorization的请求头。securityContexts则用来配置有哪些请求需要携带Token,这里我们配置了所有请求。
接下来我们再来配置两个测试接口:
@RestController
public class HelloController {
@GetMapping('/hello')
public String hello() {
return 'hello';
}
@GetMapping('/admin/hello')
public String admin() {
return 'admin';
}
}
首先在configure方法中配置资源ID和TokenStore,这里配置好之后,会自动调用JwtAccessTokenConverter将jwt解析出来,jwt里边就包含了用户的基本信息,所以就不用远程校验access_股票交易编程自动接口,token了。最后配置一下资源的拦截规则,这就是SpringSecurity中的基本写法,我就不再赘述。
我稍微解释一下:
测试
这段配置跟前面的类似,主要是SecurityScheme不同。这里采用了OAuthBuilder来构建,构建时即得配置股票交易编程自动接口,token的获取地址。
但是这种方式需要开发者先通过其他途径获取到access_股票交易编程自动接口,token,有的人会觉得这样有点麻烦,那么有没有更好的办法呢?请看方式
首先我们搭建一个名为auth-server的授权服务,搭建的时候,选择如下三个依赖:
大家可以看到,页面中多了一个Authorize按钮,点击该按钮,输入Bearer${股票交易编程自动接口,token},如下:
但是还没有将这两个结合在一起写过,所以小伙伴们对此有了疑问,想一想这还是一个非常常见的问题,因为现在使用令牌登录的场景越来越多,在这种情况下,如果使用Swagger来测试接口,要怎么在请求头中携带Token呢?今天松哥就来和大家聊一聊。
如果小伙伴们没有看过松哥之前发的OAuth2系列文章,建议一定先看下,再来看本文内容,否则接下来的内容可能会犯迷糊。
首先来配置TokenStore:
@Configuration
public class AccessTokenConfig {
@Bean
TokenStore 股票交易编程自动接口,tokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey('javaboy');
return converter;
}
}
认证方式二
我们来看下这个怎么配置。
接下来对授权服务器进行详细配置:
@EnableAuthorizationServer
@Configuration
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
@Autowired
TokenStore 股票交易编程自动接口,tokenStore;
@Autowired
ClientDetailsService clientDetailsService;
@Autowired
AuthenticationManager authenticationManager;
@Autowired
PasswordEncoder passwordEncoder;
@Autowired
JwtAccessTokenConverter jwtAccessTokenConverter;
@Bean
AuthorizationServerTokenServices 股票交易编程自动接口,tokenServices() {
DefaultTokenServices services = new DefaultTokenServices();
services.setClientDetailsService(clientDetailsService);
services.setSupportRefreshToken(true);
services.setTokenStore(股票交易编程自动接口,tokenStore);
services.setAccessTokenValiditySeconds(60 * 60 * 24 * 2);
services.setRefreshTokenValiditySeconds(60 * 60 * 24 * 7);
TokenEnhancerChain 股票交易编程自动接口,tokenEnhancerChain = new TokenEnhancerChain();
股票交易编程自动接口,tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtAccessTokenConverter));
services.setTokenEnhancer(股票交易编程自动接口,tokenEnhancerChain);
return services;
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient('javaboy')
.secret(passwordEncoder.encode('123'))
.resourceIds('res1')
.authorizedGrantTypes('password', 'refresh_股票交易编程自动接口,token')
.scopes('all')
.redirectUris('http://localhost:8082/index.html');
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.股票交易编程自动接口,tokenServices(股票交易编程自动接口,tokenServices());
}
}
请求头加参数,这里给大家介绍两种,先来看第一种。
项目创建成功之后,先把前面的AccessTokenConfig拷贝到资源服务器上,然后添加如下配置:
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Autowired
TokenStore 股票交易编程自动接口,tokenStore;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId('res1').股票交易编程自动接口,tokenStore(股票交易编程自动接口,tokenStore);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers('/admin/**').hasRole('admin')
.anyRequest().authenticated();
}
}
配置完成后,我们还需要给swagger-ui放行,否则swagger-ui相关的静态资源会被SpringSecurity拦截下来:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers('/swagger-ui.html')
.antMatchers('/webjars/**')
.antMatchers('/v2/**')
.antMatchers('/swagger-resources/**');
}
}
配置完成后,重启user-server,浏览器输入http://localhost:8081/swagger-uhtml,结果如下:
好啦,小伙伴们如果觉得有收获,记得点个在看鼓励下松哥哦~
接下来,我们在user-server中加入swagger功能,首先我们加入swagger依赖:
io.springfox
springfox-swagger2
2.9.2
io.springfox
springfox-swagger-ui
2.9.2
TokenStore我们使用JwtTokenStore这个实例。使用了JWT,access_股票交易编程自动接口,token实际上就不用存储了,因为用户的所有信息都在jwt里边,所以这里配置的JwtTokenStore本质上并不是做存储。另外我们还提供了一个JwtAccessTokenConverter,这个JwtAccessTokenConverter可以实现将用户信息和JWT进行转换。在JWT字符串生成的时候,我们需要一个签名,这个签名需要自己保存好。
看到这个问题,松哥忽然想到我自己之前写过SpringBoot+Swagger的用法:
这里松哥搭建一个OAuth2+JWT的环境来做演示。一共搭建两个服务:
auth-server | 8080 | 授权服务器 |
user-server | 8081 | 资源服务器 |
主要是两方面的修改,首先是配置CorsFilter,允许跨域,如下:
@Configuration
public class GlobalCorsConfiguration {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedOrigin('*');
corsConfiguration.addAllowedHeader('*');
corsConfiguration.addAllowedMethod('*');
UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
urlBasedCorsConfigurationSource.registerCorsConfiguration('/**', corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
}
然后在SecurityConfig中开启跨域支持:
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
...
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers().antMatchers(HttpMethod.OPTIONS, '/oauth/**')
.and()
.csrf().disable().formLogin()
.and()
.cors();
}
}
环境搭建
这里的配置稍微有点长,我来给大家解释下:
项目规划
接下来我们在user-server中修改关于Docketbean的定义:
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage('org.javaboy.oauth2.res.controller'))
.paths(PathSelectors.any())
.build()
.securityContexts(Arrays.asList(securityContext()))
.securitySchemes(Arrays.asList(securityScheme()))
.apiInfo(new ApiInfoBuilder()
.description('接口文档的描述信息')
.title('微人事项目接口文档')
.contact(new Contact('javaboy','http://www.javaboy.org','wangsong0210@gmail.com'))
.version('v1.0')
.license('Apache2.0')
.build());
}
private AuthorizationScope[] scopes() {
return new AuthorizationScope[]{
new AuthorizationScope('all', 'all scope')
};
}
private SecurityScheme securityScheme() {
GrantType grant = new ResourceOwnerPasswordCredentialsGrant('http://localhost:8080/oauth/股票交易编程自动接口,token');
return new OAuthBuilder().name('OAuth2')
.grantTypes(Arrays.asList(grant))
.scopes(Arrays.asList(scopes()))
.build();
}
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(Arrays.asList(new SecurityReference('OAuth2', scopes())))
.forPaths(PathSelectors.any())
.build();
}
}
想让OAuth2和JWT在一起愉快玩耍?请看松哥的表演
输入完成后,点击Authorize按钮,完成认证,接下来,user-server中的各种接口就可以直接调用测试了。
项目创建完成后,首先提供一个SpringSecurity的基本配置:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser('sang')
.password(passwordEncoder().encode('123'))
.roles('admin')
.and()
.withUser('javaboy')
.password(passwordEncoder().encode('123'))
.roles('user');
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().formLogin();
}
}
基本的用户信息配置完成后,接下来我们来配置授权服务器。
接下来我们搭建一个资源服务器。大家网上看到的例子,资源服务器大多都是和授权服务器放在一起的,如果项目比较小的话,这样做是没问题的,但是如果是一个大项目,这种做法就不合适了。
这段代码有点长,我来给大家挨个解释:
好了,配置完成,重启auth-server和user-server进行测试。测试效果就是松哥前面给出的片,不再赘述。
这段配置的目的,实际上就是配置用户。例如你想用微信登录第三方网站,在这个过程中,你得先登录微信,登录微信就要你的用户名/密码信息,那么我们在这里配置的,其实就是用户的用户名/密码/角色信息。
这里我创建了一个名为sang的用户,密码是12角色是admin。同时我还配置了一个表单登录。
先配置一个Docket实例,如下:
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage('org.javaboy.oauth2.res.controller'))
.paths(PathSelectors.any())
.build()
.securityContexts(Arrays.asList(securityContexts()))
.securitySchemes(Arrays.asList(securitySchemes()))
.apiInfo(new ApiInfoBuilder()
.description('接口文档的描述信息')
.title('微人事项目接口文档')
.contact(new Contact('javaboy','http://www.javaboy.org','wangsong0210@gmail.com'))
.version('v1.0')
.license('Apache2.0')
.build());
}
private SecurityScheme securitySchemes() {
return new ApiKey('Authorization', 'Authorization', 'header');
}
private SecurityContext securityContexts() {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.any())
.build();
}
private List defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope('xxx', '描述信息');
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Arrays.asList(new SecurityReference('Authorization', authorizationScopes));
}
}
由于swagger去请求/oauth/股票交易编程自动接口,token接口会跨域,所以我们首先要修改auth-server,使之支持跨域:
小结
这种方式最大的好处就是不用通过其他途径获取access_股票交易编程自动接口,token,直接在swagger-ui页面输入password模式的认证参数即可。非常方便,仅限于OAuth2模式。
OK,测试没问题。
这里加入的依赖有两个,一个用来生成接口数据,另一个swagger-ui用来做数据展示。
认证方式一
认证方式二就是直接在Swagger中填入认证信息,这样就不用从外部去获取access_股票交易编程自动接口,token了,效果如下:
auth-server就是我的资源服务器,用来颁发JWT令牌。user-server则是资源服务器,访问user-server上的资源,都需要携带令牌才能访问。swagger则用来给user-server上的接口生成文档。
资源服务器就是用来存放用户的资源,例如你在微信上的像、openid等信息,用户从授权服务器上拿到access_股票交易编程自动接口,token之后,接下来就可以通过access_股票交易编程自动接口,token来资源服务器请求数据。
好了,如此之后,我们的授权服务器就算是配置完成了,接下来我们启动授权服务器。
OK,这是我们项目的一个大致规划。
这段配置代码很简单,我简单的说一下:
再利用拿到的access_股票交易编程自动接口,token去访问资源服务器:
经过这两步的配置,服务端的跨域支持就开启了。
上面这种方式比较通用,不仅仅适用于OAuth也适用于其他一些自定义的股票交易编程自动接口,token登录方式。
资源服务器搭建
如此之后,我们的资源服务器就算配置成功了。
分别启动授权服务器和资源服务器,先访问授权服务器获取access_股票交易编程自动接口,token:
授权服务器搭建
我们创建一个新的SpringBoot项目,叫做user-server,作为我们的资源服务器,创建时,添加如下依赖:
也写过OAuth2+Jwt的用法:
接下来我们来搭建OAuth2测试环境。
需要注意的是,在当前案例中,我将采用OAuth2中的password模式进行登录,因此这里还需要明确的提供一个AuthenticationManager的Bean。
文章为作者独立观点,不代表股票交易接口观点