spring security4学习(二)spring-boot结合spring security实现http basic Authentication

HTTP Basic Authentication基本认证机制

HTTP为认证提供了一种原生工具。

尽管我们可以在HTTP的认证形式和cookie的基础上运行自己的认证工具,但在很多情况下,HTTP的原生认证功能就可以很好的满足要求

HTTP的质询/响应认证框架

简化的质询/响应认证框架:

分为四步-请求、质询、认证、成功  

认证协议与首部

认证协议是在HTTP认证首部中指定的。

请求:第一条请求没有认证信息

GET /family/jeff.jpg HTTP/1.1

质询:(服务器端的质询)首部是WWW-Authenticate服务器用401状态拒绝了请求,说明需要用户提供用户名和密码。认证算法是在WWW-Authenticate首部中指定的。

HTTP/1.1 401 Authorization Required

WWW-Authentication: Basic realm=”Family”

授权:首部是Authorization 客户端重新发送请求,但这一次会附加一个Authorization首部,用来说明认证算法,用户名和密码。

GET /family/jeff.jpg HTTP/1.1

Authorization: Basic YnssdjJlsdsdsdfsfsdfI

成功:首部是Authentication-Info 如果授权证书是正确的,服务器就会将200 OK文档返回。有些授权算法会在可选的Authentication-Info首部返回一些与授权会话相关的附加信息。

HTTP/1.0 200 OK

Content-Type:image/jpeg

Authorization - 授权

Authentication - 认证

以上摘自网友,下面介绍在工作中遇到的一个需求,项目中需要提供支持Basic Auth的实现。

在Spring中,配置和使用Spring Security,自定义验证过程中的主要实现接口(用户信息UserDetails,用户信息获取服务UserDetailsService,验证工具AuthenticationProvider)即可。其余的流程将由Spring自动接管,非常方便。

UserDetailsService提供了获取UserDetails的方式,只要实现UserDetailsService接口即可,最终生成用户和权限共同组成的UserDetails,在这里就可以实现从自定义的数据源

中获取用户信息了:

public class MyUserDetailsService implements UserDetailsService {

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

    System.out.println(username);

    return new UserDetails() {
      @Override
      public Collection getAuthorities() {
        return Arrays.asList(new SimpleGrantedAuthority("ROLE_DBA"));
      }

      @Override
      public String getPassword() {
        return "123456";
      }

      @Override
      public String getUsername() {
        return "denghb";
      }

      @Override
      public boolean isAccountNonExpired() {
        return true;
      }

      @Override
      public boolean isAccountNonLocked() {
        return true;
      }

      @Override
      public boolean isCredentialsNonExpired() {
        return true;
      }

      @Override
      public boolean isEnabled() {
        return true;
      }
    };
  }
}
AuthenticationProvider 提供用户UserDetails的具体验证方式,在这里可以自定义用户密码、验证方式等等。

public class DelegateAuthenticationProvider implements AuthenticationProvider {

  private MyUserDetailsService myUserDetailsService = new MyUserDetailsService();

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    String username = authentication.getName();
    String password = (String) authentication.getCredentials();
    //get remote ip address
    String remoteAddress = null;
    Object details = authentication.getDetails();
    if (details instanceof WebAuthenticationDetails) {
      WebAuthenticationDetails webDetails = (WebAuthenticationDetails) details;
      remoteAddress = webDetails.getRemoteAddress();
    }
    if (remoteAddress == null || remoteAddress.trim().length() == 0) {
      throw new BadCredentialsException("spring security not Authorized Ip");
    }
    UserDetails userDetails = myUserDetailsService.loadUserByUsername(username);
    if(userDetails == null){
      throw new BadCredentialsException("Username not found.");
    }

    Collection authorities = userDetails.getAuthorities();
    return new UsernamePasswordAuthenticationToken(username, password, Arrays
        .asList(new SimpleGrantedAuthority("ROLE_DBA")));
  }

  @Override
  public boolean supports(Class authentication) {
    return true;
  }
}
spring security启动配置:
@Configuration
@Order(1)
public class HttpBasicSecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Autowired
  private DelegateAuthenticationProvider delegateAuthenticationProvider;

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.authenticationProvider(delegateAuthenticationProvider)
        .authorizeRequests()
        .antMatchers("/api/**").hasRole("techops")
        .and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and().csrf().disable()
        .httpBasic();
  }
}
URL拦截配置:

URL拦截配置可以在上述的HttpBasicSecurityConfiguration 中配置,但是此方法适用于大方向上的配置,具体的特殊路径也可以在@Controller的注解中具体配置。

@RequestMapping(value = "/role", method = RequestMethod.GET)
    @PreAuthorize("hasAnyRole('ROLE_SUPER_ADMIN')")
    @ResponseBody
    public String homePageRole() {
        return "This my home page";
    }
spring boot 启动类:

@EnableAutoConfiguration
@Configuration
@ComponentScan(basePackageClasses={ApplicationStarter.class})
@PropertySource(value = "classpath:/config/application.yml")
@ImportResource({"classpath:spring-context.xml"})
public class ApplicationStarter {
    public static void main(String[] args) {
        SpringApplication.run(ApplicationStarter.class, args);
    }
    
    @Value("${domainCode}")
    private String domainCode;

    @Bean
    public DomainDefine domainDefine() {
        DomainDefine domainDefine = new DomainDefine();
        domainDefine.setDomainCode(domainCode);
        domainDefine.setUserInfoClass("com.dianrong.uniauth.ssclient.bean.SSClientUserExtInfo");
        domainDefine.setRejectPublicInvocations(false);
        domainDefine.setCustomizedLoginRedirecUrl("/content");
        return domainDefine;
    }

    @Bean
    public DelegateAuthenticationProvider delegateAuthenticationProvider() {
        return new DelegateAuthenticationProvider()
            /*.setDomainDefine(domainCode)*/;
    }
}
结果展示:例如访问:http://localhost:8180/api

这种方式去访问:就需要有"techops"权限。第一次进入页面,会有弹出框提示输入用户名和密码。
spring security4学习(二)spring-boot结合spring security实现http basic Authentication_第1张图片


输入正确的用户名和密码之后,通过谷歌控制台可以看到请求头部有加密后的用户名和密码。

spring security4学习(二)spring-boot结合spring security实现http basic Authentication_第2张图片

但是我们没有是"techops"的权限,就会看到下面403页面,即没有权限进入。

spring security4学习(二)spring-boot结合spring security实现http basic Authentication_第3张图片

你可能感兴趣的:(Spring)