前言
之前写过应用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@RefreshScopepublic class Xxxx { @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } public static void main(String[] args) { SpringApplication.run(Xxxx.class, args); }}
3、创立JWTTokenStoreConfig
类,配置和解析token
@Configurationpublic 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
类配置拜访权限以及自定义异样
@Configurationpublic 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
类
@Componentpublic 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的自定义异样