修改用户为服务
1.复制项目microservice-provider-user,将ArtfactId修改为microservice-provider-user-with-auth。
2.微服务添加如下依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
3.创建Spring Security的配置类
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception{
//所有的请求,都需要经过HTTP basic认证
http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
}
@Bean
public PasswordEncoder passwordEncoder(){
//明文编码器。这是一个不做任何操作的密码编码器,是Spring提供给我们做明文测试的
// A password encoder that does nothing. Useful for testing where working with plain text
return NoOpPasswordEncoder.getInstance();
}
@Autowired
private CustomUserDetailsService userDatailsService ;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(this.userDatailsService).passwordEncoder(this.passwordEncoder());
}
@Component
class CustomUserDetailsService implements UserDetailsService {
/**
* 模拟两个账号
* 1. 账号是user ,密码是password1 角色是user-role
* 2. 账号是admin,密码是password2 角色是admin-role
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{
if ("user".equals(username)){
return new SecurityUser("user", "password1", "user-role");
}else if ("admin".equals(username)){
return new SecurityUser("admin", "password2", "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(){
}
private Long id;
private String username;
private String password;
private String role;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(this.role);
authorities.add(authority);
return authorities;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public String getPassword() {
return this.password;
}
@Override
public String getUsername() {
return this.username;
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public String getRole() {
return this.role;
}
public void setRole(String role) {
this.role = role;
}
}
代码中模拟了两个账号: user和admin,他们的密码分别是password1和password2,角色分别为user-role和admin-role。
4.修改Controller,在其中打印当前登录的用户信息。
@RestController
public class UserController {
@Autowired
private UserRepository userRepository;
private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class);
@GetMapping("/{id}")
public User findById(@PathVariable Long id) {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if(principal instanceof UserDetails){
UserDetails user = (UserDetails) principal;
Collection<? extends GrantedAuthority> collection = user.getAuthorities();
for (GrantedAuthority c : collection){
//打印当前登录用户的信息
UserController.LOGGER.info("当前用户是{},角色是{}",user.getUsername(), c.getAuthority());
}
}else{
//do other things
}
User findOne = this.userRepository.findById(id).get();
return findOne;
}
}
测试
1.启动microservice-discovery-eureka。
2.启动microservice-provider-user-with-auth。
3.访问http://localhost:8000/1,会弹出登录对话框。
4.使用user/password1登录,可看到如下日志。
5.使用admin/password2登录,可看到如下日志。
修改电影微服务
1.复制项目microservice-consumer-movie-feign,将ArtifactId修改为microservice-consumer-movie-feign-manual。
2.去掉Feign接口UserFeignClient上的@FeignClient注解
3.去掉启动类上@EnableFeignClients注解
4.修改Controller如下:
@Import(FeignClientsConfiguration.class)
@RestController
public class MovieController {
private UserFeignClient userUserFeignClient;
private UserFeignClient adminUserFeignClient;
@Autowired
public MovieController(Decoder decoder, Encoder encoder, Client client, Contract contract){
//这边的decoder、encoder、client、contract,可以Debug看看是什么实例
this.userUserFeignClient = Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract)
.requestInterceptor(new BasicAuthRequestInterceptor("user", "password1"))
.target(UserFeignClient.class, "http://users/");
this.adminUserFeignClient= Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract)
.requestInterceptor(new BasicAuthRequestInterceptor("admin","password2"))
.target(UserFeignClient.class, "http://users/");
}
@GetMapping("/user-user/{id}")
public User findByIdUser(@PathVariable Long id){
return this.userUserFeignClient.findById(id);
}
@GetMapping("/user-admin/{id}")
public User findByIdAdmin(@PathVariable Long id){
return this.adminUserFeignClient.findById(id);
}
}
测试
1.启动microservice-discovery-eureka。
2.启动microservice-provider-user-with-auth。
3.启动microservice-consumer-movie-feign-manual。
4.访问http://localhost:8010/user-user/1,微服务打印如下日志。
5.访问http://localhost:8010/user-admin/1,微服务打印如下日志。
本文大部分内容转载自周立的《Spring Cloud与Docker微服务架构实战》