前言

之前写过应用springsecurity搭建认证服务SpringSecurity+Oauth2:明码受权模式获取Token(MongoDB+JWT),这篇则写对于如何搭建资源服务,只有验证通过的token能力拜访。

操作

1、配置Pom.xml援用spring-cloud-securityoauth2的jar包
2、配置主类@EnableResourceServer注解,开启资源服务
3、创立JWTTokenStoreConfig类,配置和解析token
4、创立ResourceServerConfiguration类配置拜访权限以及自定义异样
5、自定义springsecurity异样信息(留神:认证和资源服务的自定义异样是对立的没有区别,上面会阐明)

1、配置Pom.xml援用spring-cloud-securityoauth2的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的自定义异样