1、ResourceServerConfigurerAdapter被配置为不同的端点(参见antMatchers),而WebSecurityConfigurerAdapter不是。
这两个适配器之间的区别在于,RealServServer配置适配器使用一个特殊的过滤器来检查请求中的承载令牌,以便通过OAuth2对请求进行认证。WebSecurityConfigurerAdapter适配器用于通过会话对用户进行身份验证(如表单登录)
2、WebSecurityConfigurerAdapter是默认情况下spring security的http配置,ResourceServerConfigurerAdapter是默认情况下spring security oauth2的http配置 在ResourceServerProperties中,定义了它的order默认值为SecurityProperties.ACCESS_OVERRIDE_ORDER - 1;是大于1的,即WebSecurityConfigurerAdapter的配置的拦截要优先于ResourceServerConfigurerAdapter,优先级高的http配置是可以覆盖优先级低的配置的。
3、某些情况下如果需要ResourceServerConfigurerAdapter的拦截优先于WebSecurityConfigurerAdapter需要在配置文件中添加
security.oauth2.resource.filter-order=99
注意:
@EnableWebSecurity 注解标注的security类创建了一个WebSecurityConfigurerAdapter,且自带了硬编码的order=3,使用spring security而不是auth,即http保护
本项目采用springcloud架构
gateway用网关服务
权限系统采用:
关于auth2使用
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
搭建认证服务:
1. 在启动类加上授权服务加入@EnableAuthorizationServer这个注解,整个项目就是授权服务,然后再构建配置类,放入clientid等信息
继承AuthorizationServerConfigurerAdapter类
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("goodsClient")//客户端id
.secret(new BCryptPasswordEncoder().encode("goods123"))//客户端密钥
.resourceIds("goodsRes")//客户端资源id
.authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "refresh_token")//客户端支持认证格式
.scopes("goods")//授权范围标识
.autoApprove(false)//是否弹出授权页面 false弹出/true关闭
.redirectUris("http://www.baidu.com")//认证成功跳转页面
.and()
.withClient("resourceClient")
.secret(new BCryptPasswordEncoder().encode("resource123"))
.resourceIds("resourceRes")
.refreshTokenValiditySeconds(10000)
.authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "refresh_token")
.scopes("resource")
.autoApprove(false)
.redirectUris("http://www.baidu.com")
.and()
.withClient("schemeClient")
.secret(new BCryptPasswordEncoder().encode("scheme123"))
.resourceIds("schemeRes")
.refreshTokenValiditySeconds(10000)
.authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "refresh_token")
.scopes("resource")
.autoApprove(false)
.redirectUris("http://www.baidu.com");
}
等配置
2.资源端加入
@EnableResourceServer在启动类的时候,
继承ResourceServerConfigurerAdapter类,
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("resourceRes")
.tokenServices(tokenServices())
.stateless(true);
}
然后就可以跑起来了
测试
回车
返回授权码codehttps://www.baidu.com/?code=21F5bK
然后访问resource项目
基于上面的进行token改造
1.生成bean
@Configuration
@ConditionalOnProperty(prefix = "type",name="storeType",havingValue = "jwt",matchIfMissing = true)
public class JwtTokenConfig{
//将东西放到jwtToken里面
@Bean
public TokenStore tokenStore(){
System.out.println("c*********产生jwt密钥");
return new JwtTokenStore(jwtAccessTokenConverter());
}
//密钥签发令牌
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter jwtAccessTokenConverter=new JwtAccessTokenConverter();
jwtAccessTokenConverter.setSigningKey("123456");
return jwtAccessTokenConverter;
}
2.将增强器放入AuthorizationServerEndpointsConfigurer endpoints中
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
enhancerChain.setTokenEnhancers(Arrays.asList(jwtAccessTokenConverter));
defaultTokenServices.setTokenEnhancer(enhancerChain);
即可完成。
目标:实现将信息封装在token中,通过增强器
1. @Bean
@ConditionalOnMissingBean(name="jwtTokenEnhancer")
public TokenEnhancer jwtTokenEnhancer(){
System.out.println("c*********jwtTokenEnhancer");
return new JwtTokenEnhancer();
}
2.
public class JwtTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
Map<String,Object> info=new HashMap<String,Object>();
info.put("company","qi");
info.put("test","测试");
((DefaultOAuth2AccessToken)accessToken).setAdditionalInformation(info);
return accessToken;
}
}
3.重新写增强器
TokenEnhancerChain enhancerChain = new TokenEnhancerChain(); enhancerChain.setTokenEnhancers(Arrays.asList(jwtTokenEnhancer,jwtAccessTokenConverter));
defaultTokenServices.setTokenEnhancer(enhancerChain);
在资源里面写解析
@GetMapping("/me1")//对于jwt的请求改变,因为jwt返回的是一个字符串
public Object getCurrentUser(Authentication user, HttpServletRequest request){
Object object=SecurityContextHolder.getContext().getAuthentication().getPrincipal();
//获取头,并且进行剥离
String header=request.getHeader("Authorization");
String token= StringUtils.substringAfter(header,"bearer ");
//对token进行解析,获取额外添加的信息
try {
Claims claims = Jwts.parser().setSigningKey("123456".getBytes("UTF-8")).parseClaimsJws(token).getBody();
String company=(String)claims.get("company");
System.out.println("company:"+company);
}catch(Exception e){
e.printStackTrace();
}
return user;
}
注意token返回的@AuthenticationPrincipal UserDetails user是字符串,所以这个写法要换一下
@GetMapping("/me1")//对于jwt的请求改变,因为jwt返回的是一个字符串
public Object getCurrentUser(Authentication user, HttpServletRequest request){
Object object=SecurityContextHolder.getContext().getAuthentication().getPrincipal();
//获取头,并且进行剥离
String header=request.getHeader("Authorization");
String token= StringUtils.substringAfter(header,"bearer ");
//对token进行解析,获取额外添加的信息
try {
Claims claims = Jwts.parser().setSigningKey("123456".getBytes("UTF-8")).parseClaimsJws(token).getBody();
String company=(String)claims.get("company");
System.out.println("company:"+company);
}catch(Exception e){
e.printStackTrace();
}
return user;
}
密码模式访问:password
密码请求(post请求)
验证token是否是有效请求(get请求)
刷新token(post请求)