当前位置: 移动技术网 > IT编程>开发语言>Java > 详解spring security 配置多个AuthenticationProvider

详解spring security 配置多个AuthenticationProvider

2019年07月22日  | 移动技术网IT编程  | 我要评论

gta4满街出租车,洪荒玉兔,刘昊坤

前言

发现很少关于spring security的文章,基本都是入门级的,配个userservicedetails或者配个路由控制就完事了,而且很多还是xml配置,国内通病...so,本文里的配置都是java配置,不涉及xml配置,事实上我也不会xml配置

spring security的大体介绍

spring security本身如果只是说配置,还是很简单易懂的(我也不知道网上说spring security难,难在哪里),简单不需要特别的功能,一个websecurityconfigureradapter的实现,然后实现userservicedetails就是简单的数据库验证了,这个我就不说了。

spring security大体上是由一堆filter(所以才能在spring mvc前拦截请求)实现的,filter有几个,登出filter(logoutfilter),用户名密码验证filter(usernamepasswordauthenticationfilter)之类的,filter再交由其他组件完成细分的功能,例如最常用的usernamepasswordauthenticationfilter会持有一个authenticationmanager引用,authenticationmanager顾名思义,验证管理器,负责验证的,但authenticationmanager本身并不做具体的验证工作,authenticationmanager持有一个authenticationprovider集合,authenticationprovider才是做验证工作的组件,authenticationmanager和authenticationprovider的工作机制可以大概看一下这两个的java doc,然后成功失败都有相对应该handler 。大体的spring security的验证工作流程就是这样了。

开始配置多authenticationprovider

首先,写一个内存认证的authenticationprovider,这里我简单地写一个只有root帐号的authenticationprovider

package com.scau.equipment.config.common.security.provider;

import org.springframework.security.authentication.authenticationprovider;
import org.springframework.security.authentication.usernamepasswordauthenticationtoken;
import org.springframework.security.core.authentication;
import org.springframework.security.core.authenticationexception;
import org.springframework.security.core.grantedauthority;
import org.springframework.security.core.authority.simplegrantedauthority;
import org.springframework.security.core.userdetails.user;
import org.springframework.stereotype.component;

import java.util.arrays;
import java.util.list;

/**
 * created by administrator on 2017-05-10.
 */
@component
public class inmemoryauthenticationprovider implements authenticationprovider {
  private final string adminname = "root";
  private final string adminpassword = "root";

  //根用户拥有全部的权限
  private final list<grantedauthority> authorities = arrays.aslist(new simplegrantedauthority("can_search"),
      new simplegrantedauthority("can_search"),
      new simplegrantedauthority("can_export"),
      new simplegrantedauthority("can_import"),
      new simplegrantedauthority("can_borrow"),
      new simplegrantedauthority("can_return"),
      new simplegrantedauthority("can_repair"),
      new simplegrantedauthority("can_discard"),
      new simplegrantedauthority("can_empowerment"),
      new simplegrantedauthority("can_breed"));

  @override
  public authentication authenticate(authentication authentication) throws authenticationexception {
    if(ismatch(authentication)){
      user user = new user(authentication.getname(),authentication.getcredentials().tostring(),authorities);
      return new usernamepasswordauthenticationtoken(user,authentication.getcredentials(),authorities);
    }
    return null;
  }

  @override
  public boolean supports(class<?> authentication) {
    return true;
  }

  private boolean ismatch(authentication authentication){
    if(authentication.getname().equals(adminname)&&authentication.getcredentials().equals(adminpassword))
      return true;
    else
      return false;
  }
}

support方法检查authentication的类型是不是这个authenticationprovider支持的,这里我简单地返回true,就是所有都支持,这里所说的authentication为什么会有多个类型,是因为多个authenticationprovider可以返回不同的authentication。

public authentication authenticate(authentication authentication) throws authenticationexception 方法就是验证过程。

如果authenticationprovider返回了null,authenticationmanager会交给下一个支持authentication类型的authenticationprovider处理。

 另外需要一个数据库认证的authenticationprovider,我们可以直接用spring security提供的daoauthenticationprovider,设置一下userservicedetails和passwordencoder就可以了

 @bean
  daoauthenticationprovider daoauthenticationprovider(){
    daoauthenticationprovider daoauthenticationprovider = new daoauthenticationprovider();
    daoauthenticationprovider.setpasswordencoder(new bcryptpasswordencoder());
    daoauthenticationprovider.setuserdetailsservice(userservicedetails);
    return daoauthenticationprovider;
  }

最后在websecurityconfigureradapter里配置一个含有以上两个authenticationprovider的authenticationmanager,依然重用spring security提供的providermanager

package com.scau.equipment.config.common.security;

import com.scau.equipment.config.common.security.handler.ajaxloginfailurehandler;
import com.scau.equipment.config.common.security.handler.ajaxloginsuccesshandler;
import com.scau.equipment.config.common.security.provider.inmemoryauthenticationprovider;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.security.authentication.authenticationmanager;
import org.springframework.security.authentication.providermanager;
import org.springframework.security.authentication.dao.daoauthenticationprovider;
import org.springframework.security.config.annotation.authentication.builders.authenticationmanagerbuilder;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.inmemoryuserdetailsmanagerconfigurer;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.userdetailsmanagerconfigurer;
import org.springframework.security.config.annotation.web.builders.httpsecurity;
import org.springframework.security.config.annotation.web.builders.websecurity;
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.userdetailsservice;
import org.springframework.security.crypto.bcrypt.bcryptpasswordencoder;

import java.util.arrays;
import java.util.list;

/**
 * created by administrator on 2017/2/17.
 */
@configuration
public class securityconfig extends websecurityconfigureradapter {

  @autowired
  userdetailsservice userservicedetails;

  @autowired
  inmemoryauthenticationprovider inmemoryauthenticationprovider;

  @bean
  daoauthenticationprovider daoauthenticationprovider(){
    daoauthenticationprovider daoauthenticationprovider = new daoauthenticationprovider();
    daoauthenticationprovider.setpasswordencoder(new bcryptpasswordencoder());
    daoauthenticationprovider.setuserdetailsservice(userservicedetails);
    return daoauthenticationprovider;
  }

  @override
  protected void configure(httpsecurity http) throws exception {
    http
        .csrf().disable()
        .rememberme().alwaysremember(true).tokenvalidityseconds(86400).and()
        .authorizerequests()
          .antmatchers("/","/*swagger*/**", "/v2/api-docs").permitall()
          .anyrequest().authenticated().and()
        .formlogin()
          .loginpage("/")
          .loginprocessingurl("/login")
          .successhandler(new ajaxloginsuccesshandler())
          .failurehandler(new ajaxloginfailurehandler()).and()
        .logout().logouturl("/logout").logoutsuccessurl("/");
  }

  @override
  public void configure(websecurity web) throws exception {
    web.ignoring().antmatchers("/public/**", "/webjars/**", "/v2/**", "/swagger**");
  }

  @override
  protected authenticationmanager authenticationmanager() throws exception {
    providermanager authenticationmanager = new providermanager(arrays.aslist(inmemoryauthenticationprovider,daoauthenticationprovider()));
    //不擦除认证密码,擦除会导致tokenbasedremembermeservices因为找不到credentials再调用userdetailsservice而抛出usernamenotfoundexception
    authenticationmanager.seterasecredentialsafterauthentication(false);
    return authenticationmanager;
  }

  /**
   * 这里需要提供userdetailsservice的原因是remembermeservices需要用到
   * @return
   */
  @override
  protected userdetailsservice userdetailsservice() {
    return userservicedetails;
  }
}

基本上都是重用了原有的类,很多都是默认使用的,只不过为了修改下行为而重新配置。其实如果偷懒,直接用一个userdetailsservice,在里面做各种认证也是可以的~不过这样就没意思了

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网