SpringCloud OAuth2 和 Security 基础框架相关问题汇总

一、公共模块与微服务模块配置类无法生效问题

首先公共异常处理类中的各个注解需要被识别才能够生效

file

需要在使用该处理异常类的启动器类中的SpringBootApplication 添加对该异常类所在包的扫描

file

注意:平常SpirngBootApplication不进行属性配置,默认扫描启动类所在的包,所以在配置了扫描其他包的时候,也要配置自身启动类所在的包,还有该服务需要依赖公共模块

实战

通用模块 mms-common (com.xx.common.config.resource)中的 ResourceServerConfig.java 配置类引入到 mms-system 没有生效,折腾了两天时间,终于找到了问题,即服务启动时,只扫描启动类的包,其他引入的公共模块的包的配置类不会自动引入,所以,这里需要在启动类开启扫描包

mms-common/src/main/java/com/baidu/common/config/resource/ResourceServerConfig.java

package com.homay.common.config.resource;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.util.FileCopyUtils;

/**
 * 资源服务配置
 *
 * @description
 * 每个微服务应用都是一个资源服务器,外部访问都需要token才能进行
 *
 * @author: kaiyi
 * @Date 2021/7/14 14:04
 */
@Slf4j
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        log.info("====================进入到 【mms-common】 [ResourceServerConfig] HttpSecurity configure method ====================");

        http.csrf().disable() // 由于使用的是JWT,我们这里不需要csrf
                .sessionManagement().disable()  // 基于token,所以不需要session
                .authorizeRequests()
                .antMatchers("/user/test").permitAll()  // 匹配不需要资源认证
                .antMatchers("/**").authenticated()  //匹配需要资源认证路径
                .and().headers().cacheControl();
    }

    /**
     * 设置公钥
     *
     * @param resources
     * @throws Exception
     */
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.tokenStore(jwtTokenStore());

    }

    private TokenStore jwtTokenStore() {
        JwtTokenStore jwtTokenStore = new JwtTokenStore(accessTokenConverter());
        return jwtTokenStore;
    }

    @Bean // 放在ioc容器的
    public JwtAccessTokenConverter accessTokenConverter()  {
        //resource 验证token(公钥) authorization 产生 token (私钥)
        JwtAccessTokenConverter tokenConverter = new JwtAccessTokenConverter();
        String publicKey = null;
        try {
            ClassPathResource classPathResource = new ClassPathResource("baidu-mms.pub");
            byte[] bytes = FileCopyUtils.copyToByteArray(classPathResource.getInputStream());
            publicKey = new String(bytes, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 不设置这个会出现 Cannot convert access token to JSON [20210712]
        tokenConverter.setVerifierKey(publicKey);
        // tokenConverter.setVerifier(new RsaVerifier(publicKey));

        return tokenConverter;
    }
}

System模块启动类

package com.homay.system;

import com.homay.common.annotation.EnableCustomConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * 系统模块
 *
 * @author: kaiyi
 * @Date 2021/7/18 0:31
 */
// @EnableCustomConfig
// 开启扫描包
@SpringBootApplication(scanBasePackages = {"com.baidu.system", "com.baidu.common"})
// @SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class SystemApplication {
    public static void main(String[] args) {
        SpringApplication.run(SystemApplication.class, args);

        System.out.println("(♥◠‿◠)ノ゙  System启动成功    ");
    }
}

如果觉得上边的开启扫描包方法不太优雅,可以使用注解方式引入加载配置类:

// 开启扫描包
@SpringBootApplication(scanBasePackages = {"com.baidu.system", "com.baidu.common"})

改为:

@EnableCustomConfig
@SpringBootApplication

自定义注解类:
mms-common/src/main/java/com/baidu/common/annotation/EnableCustomConfig.java

package com.baid.common.annotation;

import com.baidu.common.config.feign.FeignAutoConfiguration;
import com.baidu.common.config.resource.ResourceServerConfig;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;
import org.springframework.scheduling.annotation.EnableAsync;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 开启自定义配置注解类
 *
 * @author: kaiyi
 * @Date 2021/7/27 16:12
 */

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
// 表示通过aop框架暴露该代理对象,AopContext能够访问
@EnableAspectJAutoProxy(exposeProxy = true)
// 开启线程异步执行
@EnableAsync
// 自动加载类
@Import({ ResourceServerConfig.class})
public @interface EnableCustomConfig {
}

调试

file

file

file

为者常成,行者常至