共计 5444 个字符,预计需要花费 14 分钟才能阅读完成。
前言
之前写过应用 springsecurity 搭建认证服务 SpringSecurity+Oauth2:明码受权模式获取 Token(MongoDB+JWT),这篇则写对于如何搭建资源服务,只有验证通过的 token 能力拜访。
操作
1、配置 Pom.xml 援用 spring-cloud-security
和oauth2
的 jar 包
2、配置主类@EnableResourceServer
注解,开启资源服务
3、创立JWTTokenStoreConfig
类,配置和解析 token
4、创立 ResourceServerConfiguration
类配置拜访权限以及自定义异样
5、自定义springsecurity
异样信息 ( 留神:认证和资源服务的自定义异样是对立的没有区别,上面会阐明)
1、配置 Pom.xml 援用 spring-cloud-security
和oauth2
的 jar 包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-security</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
2、配置主类 @EnableResourceServer 注解,开启资源服务
@SpringBootApplication
// 资源爱护服务
@EnableResourceServer
// 服务发现
@EnableDiscoveryClient
@EnableFeignClients
@RefreshScope
public class Xxxx {
@Bean
public BCryptPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();
}
public static void main(String[] args) {SpringApplication.run(Xxxx.class, args);
}
}
3、创立 JWTTokenStoreConfig
类,配置和解析 token
@Configuration
public class JWTTokenStoreConfig {
@Autowired
private ServiceConfig serviceConfig;
//JWT
@Bean
public TokenStore tokenStore() {return new JwtTokenStore(jwtAccessTokenConverter());
}
//JWT
@Bean
@Primary
public DefaultTokenServices tokenServices() {DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
//JWT
// 从配置文件中获取 jwt key,而后本人解析 token 是否无效,@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(serviceConfig.getJwtSigningKey());
return converter;
}
}
4、创立 ResourceServerConfiguration
类配置拜访权限以及自定义异样
@Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter{
@Override
public void configure(ResourceServerSecurityConfigurer resources) {OAuth2AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
authenticationEntryPoint.setExceptionTranslator(new CustomOAuthWebResponseExceptionTranslator());
resources.authenticationEntryPoint(authenticationEntryPoint);
OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler = new OAuth2AccessDeniedHandler();
oAuth2AccessDeniedHandler.setExceptionTranslator(new CustomOAuthWebResponseExceptionTranslator());
resources.accessDeniedHandler(oAuth2AccessDeniedHandler);
}
@Override
public void configure(HttpSecurity http) throws Exception {http.authorizeRequests()
// 放开 /sendRegisterEmailMessage,不须要校验 token
.antMatchers("/websocket/**").permitAll()
.antMatchers("/info/**").permitAll()
.anyRequest().authenticated();
}
}
5、自定义 springsecurity
异样信息
创立 CustomOAuthException
类
@JsonSerialize(using = CustomOAuthExceptionSerializer.class)
public class CustomOAuthException extends OAuth2Exception {private static Logger log = LoggerFactory.getLogger(CustomOAuthException.class);
private String oAuth2ErrorCode;
private int httpErrorCode;
public CustomOAuthException(String msg, String oAuth2ErrorCode, int httpErrorCode) {super(msg);
this.oAuth2ErrorCode = oAuth2ErrorCode;
this.httpErrorCode = httpErrorCode;
}
}
创立 CustomOAuthExceptionSerializer
类
public class CustomOAuthExceptionSerializer extends StdSerializer<CustomOAuthException> {private static Logger log = LoggerFactory.getLogger(CustomOAuthExceptionSerializer.class);
protected CustomOAuthExceptionSerializer() {super(CustomOAuthException.class);
}
@Override
public void serialize(CustomOAuthException e, JsonGenerator generator, SerializerProvider serializerProvider) throws IOException {generator.writeStartObject();
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
generator.writeObjectField("error",e.getOAuth2ErrorCode());
generator.writeObjectField("status", e.getHttpErrorCode());
generator.writeObjectField("message", e.getMessage());
generator.writeObjectField("path", request.getServletPath());
generator.writeObjectField("timestamp", (new Date()).getTime());
if (e.getAdditionalInformation() != null) {for (Map.Entry<String, String> entry : e.getAdditionalInformation().entrySet()) {String key = entry.getKey();
String add = entry.getValue();
generator.writeObjectField(key, add);
}
}
generator.writeEndObject();}
}
创立 CustomOAuthWebResponseExceptionTranslator
类
@Component
public class CustomOAuthWebResponseExceptionTranslator extends DefaultWebResponseExceptionTranslator {private ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer();
private static Logger log = LoggerFactory.getLogger(CustomOAuthWebResponseExceptionTranslator.class);
@Override
public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {ResponseEntity<OAuth2Exception> translate = super.translate(e);
OAuth2Exception body = translate.getBody();
CustomOAuthException customOauthException = new CustomOAuthException(body.getMessage(),body.getOAuth2ErrorCode(),body.getHttpErrorCode());
ResponseEntity<OAuth2Exception> response = new ResponseEntity<>(customOauthException, translate.getHeaders(), translate.getStatusCode());
return response;
}
}
最初如果用户名或明码谬误则返回上面的错误信息:
{
timestamp: 1658149719489,
path: '/oauth/token',
error: 'invalid_request',
message: '用户名或明码谬误'
status: 400
}
如果 token 谬误则返回上面的错误信息:
{
timestamp: 1658149719489,
path: '/oauth/token',
error: 'invalid_request',
message: 'token 谬误或过期'
status: 400
}
如果 refresh_token 谬误则返回上面的错误信息:
{
timestamp: 1658149719489,
path: '/oauth/token',
error: 'invalid_request',
message: 'refresh_token 谬误或过期'
status: 400
}
资源服务的目录构造
认证服务的目录构造
总结
1、springsecurity 自带的异样信息不合乎本人的需要的时候就要自定义返回错误信息
2、错误信息返回的错误码如果是 401 那么照样返回 401,如果感觉 401 不太好能够自行设置
援用
SpringBoot Security 的自定义异样
正文完
发表至: spring-security
2022-07-18