中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

SpringSecurity自(zi)定(ding)義AuthenticationProvider和AuthenticationFilter

AuthenticationProvider

  • 默認實現:DaoAuthenticationProvider

授權方式提供者(zhe),判(pan)斷授權有(you)效(xiao)性,用(yong)戶(hu)有(you)效(xiao)性,在(zai)判(pan)斷用(yong)戶(hu)是否有(you)效(xiao)性,它依(yi)賴于UserDetailsService實例,開發人員可以自(zi)定(ding)義UserDetailsService的實現(xian)。

  1. additionalAuthenticationChecks方法校驗密碼有效性
  2. retrieveUser方法根據用戶名獲取用戶
  3. createSuccessAuthentication完成授權持久化
@Component
@Slf4j
public class LindAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

  @Autowired
  UserDetailsService userDetailsService;

  @Autowired
  private PasswordEncoder passwordEncoder;

  /**
   * 校驗密碼有效性.
   *
   * @param userDetails    .
   * @param authentication .
   * @throws AuthenticationException .
   */
  @Override
  protected void additionalAuthenticationChecks(
      UserDetails userDetails, UsernamePasswordAuthenticationToken authentication)
      throws AuthenticationException {
    if (authentication.getCredentials() == null) {
      logger.debug("Authentication failed: no credentials provided");

      throw new BadCredentialsException(messages.getMessage(
          "AbstractUserDetailsAuthenticationProvider.badCredentials",
          "Bad credentials"));
    }

    String presentedPassword = authentication.getCredentials().toString();

    if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
      logger.debug("Authentication failed: password does not match stored value");

      throw new BadCredentialsException(messages.getMessage(
          "AbstractUserDetailsAuthenticationProvider.badCredentials",
          "Bad credentials"));
    }
  }

  /**
   * 獲取用戶.
   *
   * @param username       .
   * @param authentication .
   * @return
   * @throws AuthenticationException .
   */
  @Override
  protected UserDetails retrieveUser(
      String username, UsernamePasswordAuthenticationToken authentication)
      throws AuthenticationException {
    UserDetails loadedUser = userDetailsService.loadUserByUsername(username);
    if (loadedUser == null) {
      throw new InternalAuthenticationServiceException(
          "UserDetailsService returned null, which is an interface contract violation");
    }
    return loadedUser;
  }
}
 /**
   * 授權持久化.
   */
  @Override
  protected Authentication createSuccessAuthentication(Object principal,
                                                       Authentication authentication, UserDetails user) {
    return super.createSuccessAuthentication(principal, authentication, user);
  }

AuthenticationFilter

  • 默認實現:UsernamePasswordAuthenticationFilter

授權過濾器,你可以自定義它,并把它添加到默認過濾器前或者后去執行,主要用來到授權的持久化,它可以從請求上下文中獲取你的user,password等信息,然后去判斷它是否符合規則,最后通過authenticate方法去授權。默認的UsernamePasswordAuthenticationFilter過濾器(qi),主要判斷請(qing)求(qiu)方(fang)式是否為post,并(bing)且對username和password進(jin)行了默認值(zhi)的處理,總之,在這個過濾器(qi)里不會(hui)涉及到具體業務(wu)。

public class LindUserNameAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

  public LindUserNameAuthenticationFilter() {
    super(new AntPathRequestMatcher("/login", "GET"));
  }

  @Override
  public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
    String username = request.getParameter("username");
    String password = request.getParameter("password");

    if (username == null) {
      throw new InternalAuthenticationServiceException("Failed to get the username");
    }

    if (password == null) {
      throw new InternalAuthenticationServiceException("Failed to get the password");
    }

    UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
        username, password);
    authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
    return this.getAuthenticationManager().authenticate(authRequest);
  }
}

UserDetialsService

這是一個接口,有(you)默認的(de)(de)實現(xian)(xian)方式(shi),一般(ban)的(de)(de),我們需要(yao)根(gen)據業務(wu)去(qu)重新實現(xian)(xian)它,比如從你的(de)(de)用(yong)戶(hu)表獲取當前授權的(de)(de)用(yong)戶(hu)信息(xi),你需要(yao)在UserDetialsService實現(xian)(xian)類里對用(yong)戶(hu)表進行讀取操作;它一般(ban)會在AuthenticationProvider里的(de)(de)retrieveUser方法中被(bei)使用(yong),這就像面向對象里的(de)(de)模(mo)板方法模(mo)式(shi)一樣,springSecurity把(ba)檢驗的(de)(de)步驟設計好了(le),咱們開發只要(yao)根(gen)據規則去(qu)實現(xian)(xian)具體細節就好。

@Component
public class MyUserDetailService implements UserDetailsService {
  @Autowired
  private PasswordEncoder passwordEncoder;

  @Override
  public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
    /*
      設置用戶和角色需要注意:
      1. commaSeparatedStringToAuthorityList放入角色時需要加前綴ROLE_,而在controller使用時不需要加ROLE_前綴
      2. 放入的是權限時,不能加ROLE_前綴,hasAuthority與放入的權限名稱對應即可
    */
    List<UserDetails> userDetailsList = new ArrayList<>();
    userDetailsList.add(User.builder()
        .username("admin")
        .password(passwordEncoder.encode("123"))
        .authorities(AuthorityUtils.commaSeparatedStringToAuthorityList("read,ROLE_ADMIN")).build());
    userDetailsList.add(User.builder()
        .username("user")
        .password(passwordEncoder.encode("123"))
        .authorities(AuthorityUtils.commaSeparatedStringToAuthorityList("read,ROLE_USER"))
        .build());

    //獲取用戶
    return userDetailsList.stream()
        .filter(o -> o.getUsername().equals(name))
        .findFirst()
        .orElse(null);

  }
}

在WebSecurityConfig里開啟它

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  @Autowired
  LindAuthenticationSuccessHandler lindAuthenticationSuccessHandler;

  @Autowired
  LindAuthenticationFailHandler lindAuthenticationFailHandler;
  @Autowired
  LindAuthenticationProvider lindAuthenticationProvider;

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
        .antMatchers("/", "/index").permitAll()
        .antMatchers("/admin/**").hasRole("ADMIN")//按路由授權
        .anyRequest().authenticated()
        .and()
        .formLogin()
        .loginPage("/login")
        .defaultSuccessUrl("/hello")//默認登錄成功后跳轉的頁面
        .successHandler(lindAuthenticationSuccessHandler)
        .failureHandler(lindAuthenticationFailHandler)
        .permitAll()
        .and()
        .addFilterAt(lindAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class).authorizeRequests().and()
        .logout()
        .permitAll();
  }

  /**
   * 自定義的Filter.
   */
  @Bean
  LindUserNameAuthenticationFilter lindAuthenticationFilter() {
    LindUserNameAuthenticationFilter phoneAuthenticationFilter = new LindUserNameAuthenticationFilter();
    ProviderManager providerManager =
        new ProviderManager(Collections.singletonList(lindAuthenticationProvider));
    phoneAuthenticationFilter.setAuthenticationManager(providerManager);
    phoneAuthenticationFilter.setAuthenticationSuccessHandler(lindAuthenticationSuccessHandler);
    phoneAuthenticationFilter.setAuthenticationFailureHandler(lindAuthenticationFailHandler);
    return phoneAuthenticationFilter;
  }

  /**
   * 密碼生成策略.
   *
   * @return
   */
  @Bean
  public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }
}

認證時執行的順序

  1. LindUserNameAuthenticationFilter
  2. LindAuthenticationProvider.retrieveUser
  3. LindAuthenticationProvider.additionalAuthenticationChecks
  4. UserDetailsService
  5. Authentication

springSecurity源碼(ma):

posted @ 2019-02-19 13:41  張占嶺  閱讀(27389)  評論(1)    收藏  舉報