java B2B2C Springcloud电子商务平台源码-自定义feign配置与服务调用的安全验证

yayay · · 99 次点击 · · 开始浏览    
feign的使用,可以简化服务之间的调用,让服务之间调用更加优雅,本文从feign自定义配置和创建feign完成服务之间复杂权限验证,来进一步理解和定制feign。 需要JAVA Spring Cloud大型企业分布式微服务云构建的B2B2C电子商务平台源码 一零三八七七四六二六 自定义配置 创建Feign的配置类 ``` @Configuration public class FeignConfiguration{ @Bean public Contract feignContract(){ return new feign.Contract.Default(); } @Bean public BasicAuthRequestInterceptor basicAuthRequestInterceptor(){ return new BasicAuthRequestInterceptor("user","password"); } } ``` 说明:第一个@Bean配置是在FeignClient中的接口中使用Feign自带的注解; 第二个@Bean配置是在请求接口中要进行基于Http Basic的认证后才能调用。 FeignClient接口引用配置 ``` @FeignClient(name="hello", configuration=FeignConfiguration.class) public interface HelloService{ @RequestLine("GET /message") HelloMessage hello(); } ``` 需要注意的是: FeignConfiguration类不能包含在主应用程序上下文的@ComponentScan中,否则该配置会被所有的@FeignClient共享。 Ribbon的自定义配置中也需要注意这个问题。 服务调用的复杂权限认证 上面演示了服务之间可以通过自定义配置完成基于Http Basic的认证,但是不能满足根据不同的角色不同的用户执行不同的操作,即服务之间的调用有更复杂的权限要求,就不能满足要求了,这时候要针对feign做进一步的改进。 引入spring-security(服务提供者) ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> ``` 关键权限配置(服务提供者) ``` package com.example.helloauth.configuration; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Collection; /** * @author billjiang 475572229@qq.com * @create 17-8-26 */ @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception{ http.authorizeRequests().anyRequest().authenticated().and().httpBasic(); } @Bean public PasswordEncoder passwordEncoder(){ return NoOpPasswordEncoder.getInstance(); } @Autowired private CustomUserDetailService userDetailService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception{ auth.userDetailsService(this.userDetailService).passwordEncoder(this.passwordEncoder()); } @Component class CustomUserDetailService implements UserDetailsService{ @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{ if("user".equals(username)){ return new SecurityUser("user","123456","user-role"); }else if("admin".equals(username)){ return new SecurityUser("admin","123456","admin-role"); }else{ return null; } } } class SecurityUser implements UserDetails{ private static final long serialVersionUID=1L; public SecurityUser(String username,String password,String role){ super(); this.username=username; this.password=password; this.role=role; } public SecurityUser(){ } @Override public Collection<? extends GrantedAuthority> getAuthorities() { Collection<GrantedAuthority> authorities=new ArrayList<>(); SimpleGrantedAuthority authority=new SimpleGrantedAuthority(this.role); authorities.add(authority); return authorities; } private Long id; private String username; private String password; private String role; public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Override public String getUsername() { return username; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } public void setUsername(String username) { this.username = username; } @Override public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getRole() { return role; } public void setRole(String role) { this.role = role; } } } ``` 启动项目hello-auth后,可以见到页面需要输入用户名和密码才能访问。 服务消费者hello-auth-feign修改 去掉启动类上的@EnableFeignClients注解 去掉接口的@FeignClient的注解 ``` package com.example.helloauthconsumerfeign.service; import com.example.helloauthconsumerfeign.model.User; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; /** * @author billjiang 475572229@qq.com * @create 17-8-23 */ //@FeignClient(value="hello-auth") public interface HelloAuthService { @GetMapping("/{id}") User findById(@PathVariable("id") Long id); } ``` 编写Controller类如下 ``` package com.example.helloauthconsumerfeign.controller; import com.example.helloauthconsumerfeign.model.User; import com.example.helloauthconsumerfeign.service.HelloAuthService; import feign.Client; import feign.Contract; import feign.Feign; import feign.auth.BasicAuthRequestInterceptor; import org.springframework.beans.factory.annotation.Autowired; import feign.codec.Decoder; import feign.codec.Encoder; import org.springframework.cloud.netflix.feign.FeignClientsConfiguration; import org.springframework.context.annotation.Import; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; /** * @author billjiang 475572229@qq.com * @create 17-8-26 */ @Import(FeignClientsConfiguration.class) @RestController public class HelloAuthFeignController { private HelloAuthService userAuthService; private HelloAuthService adminAuthService; @Autowired public HelloAuthFeignController(Decoder decoder, Encoder encoder, Client client, Contract contract){ this.userAuthService= Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract) .requestInterceptor(new BasicAuthRequestInterceptor("user","123456")) .target(HelloAuthService.class,"http://hello-auth/"); this.adminAuthService= Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract) .requestInterceptor(new BasicAuthRequestInterceptor("admin","123456")) .target(HelloAuthService.class,"http://hello-auth/"); } @GetMapping("/user/{id}") public User findByIdUser(@PathVariable Long id){ return this.userAuthService.findById(id); } @GetMapping("/admin/{id}") public User findByIdAdmin(@PathVariable Long id){ return this.adminAuthService.findById(id); } } ``` 消费者调用 在浏览器器分别输入http://localhost:8031/admin/1和http://localhost:8031/user/2则可以完成服务之间授权的调用。 在实际业务中会根据不同的角色,执行不同的业务操作,基于以上示例可以在服务之间完成复杂的服务鉴权。 [java B2B2C Springcloud电子商务平台源码](https://2147775633.iteye.com/blog/2434341)
99 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet