请选择 进入手机版 | 继续访问电脑版
本站特色:极好的技术研究氛围!所有技术交流,必有回复!

疯狂Java联盟

 找回密码
 加入联盟
查看: 233|回复: 0

java B2B2C Springcloud电子商务平台源码-自定义feign配置与服务

[复制链接]
发表于 2019-1-30 10:39:24 | 显示全部楼层 |阅读模式
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则可以完成服务之间授权的调用。
在实际业务中会根据不同的角色,执行不同的业务操作,基于以上示例可以在服务之间完成复杂的服务鉴权。

您需要登录后才可以回帖 登录 | 加入联盟

本版积分规则

视频、代码、电子书下载
请关注"疯狂图书"公众号
QQ交流1群: 545923995  未满
微信群请扫二维码
QQ交流1群:
545923995
(未满)

小黑屋|手机版|Archiver|疯狂Java联盟 ( 粤ICP备11094030号 )

GMT+8, 2019-5-20 22:27 , Processed in 0.329234 second(s), 6 queries , File On.

快速回复 返回顶部 返回列表