
-
创建eureka子模块

-
pom
| <dependencies> |
| <dependency> |
| <groupId>com.mengxuegu</groupId> |
| <artifactId>mengxuegu-cloud-oauth2-base</artifactId> |
| <version>${mengxuegu-security.version}</version> |
| </dependency> |
| |
| <dependency> |
| <groupId>org.springframework.cloud</groupId> |
| <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> |
| </dependency> |
| </dependencies> |
| server: |
| port: 6001 |
| eureka: |
| instance: |
| hostname: localhost |
| client: |
| registerWithEureka: false |
| fetchRegistry: false |
| serviceUrl: |
| defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ |
| @EnableEurekaServer |
| @SpringBootApplication |
| public class EurekaServer_6001 { |
| |
| public static void main(String[] args) { |
| SpringApplication.run(EurekaServer_6001.class, args); |
| } |
| |
| } |
| |
| |
| <dependency> |
| <groupId>org.springframework.cloud</groupId> |
| <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> |
| </dependency> |
| |
| |
| @EnableEurekaClient |
| |
| |
| eureka: |
| client: |
| registerWithEureka: true |
| fetchRegistry: true |
| serviceUrl: |
| defaultZone: http://localhost:6001/eureka |
| instance: |
| instanceId: ${spring.application.name}:${server.port} |
| preferIpAddress: true |
| spring: |
| application: |
| name: auth-server |
| |
| |
| |
| |
| |
| <dependency> |
| <groupId>org.springframework.cloud</groupId> |
| <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> |
| </dependency> |
| |
| |
| @EnableEurekaClient |
| |
| |
| eureka: |
| client: |
| registerWithEureka: true |
| fetchRegistry: true |
| serviceUrl: |
| defaultZone: http://localhost:6001/eureka |
| instance: |
| instanceId: ${spring.application.name}:${server.port} |
| preferIpAddress: true |
| |
| spring: |
| application: |
| name: product-server |
| |
| |
| |
| <dependencies> |
| <dependency> |
| <groupId>com.mengxuegu</groupId> |
| <artifactId>mengxuegu-cloud-oauth2-base</artifactId> |
| <version>${mengxuegu-security.version}</version> |
| </dependency> |
| <!-- 一样作为资源服务器,所以要引入 --> |
| <dependency> |
| <groupId>org.springframework.cloud</groupId> |
| <artifactId>spring-cloud-starter-oauth2</artifactId> |
| </dependency> |
| |
| <dependency> |
| <groupId>org.springframework.cloud</groupId> |
| <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> |
| </dependency> |
| <!--zuul路由网关依赖--> |
| <dependency> |
| <groupId>org.springframework.cloud</groupId> |
| <artifactId>spring-cloud-starter-netflix-zuul</artifactId> |
| </dependency> |
| </dependencies> |
| |
| |
| server: |
| port: 7001 |
| spring: |
| application: |
| name: zuul-gateway |
| eureka: |
| client: |
| registerWithEureka: true |
| fetchRegistry: true |
| serviceUrl: |
| defaultZone: http://localhost:6001/eureka |
| instance: |
| instanceId: ${spring.application.name}:${server.port} |
| preferIpAddress: true |
| zuul: |
| sensitive-headers: null |
| add-host-header: true |
| routes: |
| authentication: |
| path: /auth/** |
| serviceId: auth-server |
| stripPrefix: false |
| product: |
| path: /product/** |
| serviceId: product-server |
| stripPrefix: false |
| |
| |
| @EnableZuulProxy //开启zuul的功能 |
| @EnableEurekaClient |
| @SpringBootApplication |
| public class ZuulServer_7001 { |
| |
| public static void main(String[] args) { |
| SpringApplication.run(ZuulServer_7001.class, args); |
| } |
| |
| } |
| @Configuration |
| public class TokenConfig { |
| |
| @Bean |
| public JwtAccessTokenConverter jwtAccessTokenConverter() { |
| JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); |
| |
| ClassPathResource resource = new ClassPathResource("public.txt"); |
| String publicKey = null; |
| try { |
| publicKey = IOUtils.toString(resource.getInputStream(), "UTF-8"); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| converter.setVerifierKey(publicKey); |
| return converter; |
| } |
| |
| @Bean |
| public TokenStore tokenStore() { |
| |
| return new JwtTokenStore(jwtAccessTokenConverter()); |
| } |
| |
| } |
- 配置资源的访问权限(即通过网关转发到认证服务器时设置为不需要权限,通过网关访问资源服务器时需要PRODUCT_API权限)
| @Configuration |
| public class ResourceServerConfig { |
| |
| public static final String RESOURCE_ID = "product-server"; |
| |
| @Autowired |
| private TokenStore tokenStore; |
| |
| |
| @Configuration |
| @EnableResourceServer |
| public class AuthResourceServerConfig extends ResourceServerConfigurerAdapter{ |
| @Override |
| public void configure(ResourceServerSecurityConfigurer resources) throws Exception { |
| resources.resourceId(RESOURCE_ID) |
| .tokenStore(tokenStore) |
| ; |
| } |
| @Override |
| public void configure(HttpSecurity http) throws Exception { |
| |
| http.authorizeRequests() |
| .anyRequest().permitAll(); |
| } |
| } |
| |
| |
| @Configuration |
| @EnableResourceServer |
| public class ProductResourceServerConfig extends ResourceServerConfigurerAdapter{ |
| @Override |
| public void configure(ResourceServerSecurityConfigurer resources) throws Exception { |
| resources.resourceId(RESOURCE_ID) |
| .tokenStore(tokenStore) |
| ; |
| } |
| @Override |
| public void configure(HttpSecurity http) throws Exception { |
| http.authorizeRequests() |
| .antMatchers("/product/**") |
| .access("#oauth2.hasScope('PRODUCT_API')"); |
| } |
| } |
| |
| } |
- 编写security配置类,放行访问网关的所有请求
| @EnableWebSecurity |
| public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { |
| |
| |
| |
| |
| |
| @Override |
| protected void configure(HttpSecurity http) throws Exception { |
| http.authorizeRequests().anyRequest().permitAll(); |
| } |
| |
| } |
| 将解析后的用户信息转发给目标微服务,这样目标微服务可以判断用户可访问的权限。 |
| 自定义过虑器需要继承 ZuulFilter,ZuulFilter是一个抽象类,需要覆盖它的4个方法,如下: |
| filterType:返回字符串代表过滤器的类型,返回值有: |
| pre:在请求路由之前执行 |
| route:在请求路由时调用 |
| post:请求路由之后调用, 也就是在route和errror过滤器之后调用 |
| error:处理请求发生错误时调用 |
| filterOrder:此方法返回整型数值,通过此数值来定义过滤器的执行顺序,数字越小优先级越高。 |
| shouldFilter:返回Boolean值,判断该过滤器是否执行。返回true表示要执行此过虑器,false不执行。 |
| run:过滤器的业务逻辑 |
| |
| |
| |
| @Component |
| public class AuthenticationFilter extends ZuulFilter { |
| |
| Logger logger = LoggerFactory.getLogger(getClass()); |
| |
| |
| @Override |
| public String filterType() { |
| return "pre"; |
| } |
| |
| |
| @Override |
| public int filterOrder() { |
| return 0; |
| } |
| |
| |
| @Override |
| public boolean shouldFilter() { |
| return true; |
| } |
| |
| @Override |
| public Object run() throws ZuulException { |
| Authentication authentication = |
| SecurityContextHolder.getContext().getAuthentication(); |
| |
| if( !(authentication instanceof OAuth2Authentication)) { |
| return null; |
| } |
| logger.info("网关获取到认证对象:" + authentication); |
| |
| Object principal = authentication.getPrincipal(); |
| |
| Collection<? extends GrantedAuthority> authorities |
| = authentication.getAuthorities(); |
| |
| Set<String> authoritySet = AuthorityUtils.authorityListToSet(authorities); |
| |
| Object details = authentication.getDetails(); |
| |
| Map<String, Object> result = new HashMap<>(); |
| result.put("principal", principal); |
| result.put("authorities", authoritySet); |
| result.put("details", details); |
| |
| RequestContext context = RequestContext.getCurrentContext(); |
| |
| String base64 = Base64Utils.encodeToString(JSON.toJSONString(result).getBytes()); |
| |
| context.addZuulRequestHeader("auth-token", base64); |
| return null; |
| } |
| |
| } |
| @Configuration |
| public class GatewayConfig { |
| |
| |
| @Bean |
| public CorsFilter corsFilter() { |
| final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); |
| final CorsConfiguration corsConfiguration = new CorsConfiguration(); |
| corsConfiguration.addAllowedHeader("*"); |
| corsConfiguration.addAllowedOrigin("*"); |
| corsConfiguration.addAllowedMethod("*"); |
| |
| corsConfiguration.addExposedHeader("Authorization"); |
| source.registerCorsConfiguration("/**", corsConfiguration); |
| return new CorsFilter(source); |
| } |
| |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术