详解spring security 配置多个AuthenticationProvider

前言

发现很少关于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,在里面做各种认证也是可以的~不过这样就没意思了

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

(0)

相关推荐

  • Spring Boot中整合Spring Security并自定义验证代码实例

    最终效果 1.实现页面访问权限限制 2.用户角色区分,并按照角色区分页面权限 3.实现在数据库中存储用户信息以及角色信息 4.自定义验证代码 效果如下: 1.免验证页面 2.登陆页面 在用户未登录时,访问任意有权限要求的页面都会自动跳转到登陆页面. 3.需登陆才能查看的页面 用户登陆后,可以正常访问页面资源,同时可以正确显示用户登录名: 4.用户有角色区分,可以指定部分页面只允许有相应用户角色的人使用 4.1.只有ADMIN觉得用户才能查看的页面(权限不足) 4.2.只有ADMIN觉得用户才能查

  • spring security自定义决策管理器

    首先介绍下Spring的决策管理器,其接口为AccessDecisionManager,抽象类为AbstractAccessDecisionManager.而我们要自定义决策管理器的话一般是继承抽象类而不去直接实现接口. 在Spring中引入了投票器(AccessDecisionVoter)的概念,有无权限访问的最终觉得权是由投票器来决定的,最常见的投票器为RoleVoter,在RoleVoter中定义了权限的前缀,先看下Spring在RoleVoter中是怎么处理授权的. public int

  • java中自定义Spring Security权限控制管理示例(实战篇)

    背景描述 项目中需要做细粒的权限控制,细微至url + httpmethod (满足restful,例如: https://.../xxx/users/1, 某些角色只能查看(HTTP GET), 而无权进行增改删(POST, PUT, DELETE)). 表设计 为避嫌,只列出要用到的关键字段,其余敬请自行脑补. 1.admin_user 管理员用户表, 关键字段( id, role_id ). 2.t_role 角色表, 关键字段( id, privilege_id ). 3.t_privi

  • 话说Spring Security权限管理(源码详解)

    最近项目需要用到Spring Security的权限控制,故花了点时间简单的去看了一下其权限控制相关的源码(版本为4.2). AccessDecisionManager spring security是通过AccessDecisionManager进行授权管理的,先来张官方图镇楼. AccessDecisionManager AccessDecisionManager 接口定义了如下方法: //调用AccessDecisionVoter进行投票(关键方法) void decide(Authent

  • Spring Boot如何使用Spring Security进行安全控制

    我们在编写Web应用时,经常需要对页面做一些安全控制,比如:对于没有访问权限的用户需要转到登录表单页面.要实现访问控制的方法多种多样,可以通过Aop.拦截器实现,也可以通过框架实现(如:Apache Shiro.spring Security). 本文将具体介绍在Spring Boot中如何使用Spring Security进行安全控制. 准备工作 首先,构建一个简单的Web工程,以用于后续添加安全控制,也可以用之前Chapter3-1-2做为基础工程.若对如何使用Spring Boot构建We

  • Java中SpringSecurity密码错误5次锁定用户的实现方法

    Spring Security简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作. 下面看下实例代码: 第

  • Spring Boot(四)之使用JWT和Spring Security保护REST API

    通常情况下,把API直接暴露出去是风险很大的,不说别的,直接被机器攻击就喝一壶的.那么一般来说,对API要划分出一定的权限级别,然后做一个用户的鉴权,依据鉴权结果给予用户开放对应的API.目前,比较主流的方案有几种: 用户名和密码鉴权,使用Session保存用户鉴权结果. 使用OAuth进行鉴权(其实OAuth也是一种基于Token的鉴权,只是没有规定Token的生成方式) 自行采用Token进行鉴权 第一种就不介绍了,由于依赖Session来维护状态,也不太适合移动时代,新的项目就不要采用了.

  • Spring security实现权限管理示例

    Spring security实现权限管理示例,具体如下: 1.配置文件 1.POM.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.o

  • 详解spring security 配置多个AuthenticationProvider

    前言 发现很少关于spring security的文章,基本都是入门级的,配个UserServiceDetails或者配个路由控制就完事了,而且很多还是xml配置,国内通病...so,本文里的配置都是java配置,不涉及xml配置,事实上我也不会xml配置 spring security的大体介绍 spring security本身如果只是说配置,还是很简单易懂的(我也不知道网上说spring security难,难在哪里),简单不需要特别的功能,一个WebSecurityConfigurerA

  • 详解spring security四种实现方式

    spring security实现方式大致可以分为这几种: 1.配置文件实现,只需要在配置文件中指定拦截的url所需要权限.配置userDetailsService指定用户名.密码.对应权限,就可以实现. 2.实现UserDetailsService,loadUserByUsername(String userName)方法,根据userName来实现自己的业务逻辑返回UserDetails的实现类,需要自定义User类实现UserDetails,比较重要的方法是getAuthorities()

  • 详解Spring Security 中的四种权限控制方式

    Spring Security 中对于权限控制默认已经提供了很多了,但是,一个优秀的框架必须具备良好的扩展性,恰好,Spring Security 的扩展性就非常棒,我们既可以使用 Spring Security 提供的方式做授权,也可以自定义授权逻辑.一句话,你想怎么玩都可以! 今天松哥来和大家介绍一下 Spring Security 中四种常见的权限控制方式. 表达式控制 URL 路径权限 表达式控制方法权限 使用过滤注解 动态权限 四种方式,我们分别来看.  1.表达式控制 URL 路径权

  • 详解Spring Security中权限注解的使用

    目录 1. 具体用法 2. SpEL 3. @PreAuthorize 最近有个小伙伴在微信群里问 Spring Security 权限注解的问题: 很多时候事情就是这么巧,松哥最近在做的 tienchin 也是基于注解来处理权限问题的,所以既然大家有这个问题,咱们就一块来聊聊这个话题. 当然一些基础的知识我就不讲了,对于 Spring Security 基本用法尚不熟悉的小伙伴,可在公众号后台回复 ss,有原创的系列教程. 1. 具体用法 先来看看 Spring Security 权限注解的具

  • 详解Spring Security如何在权限中使用通配符

    目录 前言 1. SpEL 2. 自定义权限该如何写 3. 权限通配符 4. TienChin 项目怎么做的 前言 小伙伴们知道,在 Shiro 中,默认是支持权限通配符的,例如系统用户有如下一些权限: system:user:add system:user:delete system:user:select system:user:update … 现在给用户授权的时候,我们可以像上面这样,一个权限一个权限的配置,也可以直接用通配符: system:user:* 这个通配符就表示拥有针对用户的

  • 详解Spring获取配置的三种方式

    目录 前言 Spring中获取配置的三种方式 通过@Value动态获取单个配置 通过@ConfigurationProperties+前缀方式批量获取 通过Environment动态获取单个配置 总结 前言 最近在写框架时遇到需要根据特定配置(可能不存在)加载 bean 的需求,所以就学习了下 Spring 中如何获取配置的几种方式. Spring 中获取配置的三种方式 通过 @Value 方式动态获取单个配置 通过 @ConfigurationProperties + 前缀方式批量获取配置 通

  • 详解Spring Security中获取当前登录用户的详细信息的几种方法

    目录 在Bean中获取用户信息 在Controller中获取用户信息 通过 Interface 获取用户信息 在JSP页面中获取用户信息 在Bean中获取用户信息 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (!(authentication instanceof AnonymousAuthenticationToken)) { String currentU

  • 一文详解Spring Security的基本用法

    目录 1.引入依赖 2.用户名和密码在哪里设置 3.UserDetailsService接口详解 3.1JdbcDaoImpl实现类 3.2InMemoryUserDetailsManager实现类 3.3自定义实现类实现UserDetailsService接口 4.如何修改登录页面 Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架, 提供了完善的认证机制和方法级的授权功能.是一款非常优秀的权限管理框架.它的核心是一组过滤器链,不同的功能经由不同的过滤器. 今天通

  • 详解Spring Security如何配置JSON登录

    spring security用了也有一段时间了,弄过异步和多数据源登录,也看过一点源码,最近弄rest,然后顺便搭oauth2,前端用json来登录,没想到spring security默认居然不能获取request中的json数据,谷歌一波后只在stackoverflow找到一个回答比较靠谱,还是得要重写filter,于是在这里填一波坑. 准备工作 基本的spring security配置就不说了,网上一堆例子,只要弄到普通的表单登录和自定义UserDetailsService就可以.因为需

  • 详解Spring Security的Web应用和指纹登录实践

    前言 Java 开发人员在解决 Web 应用安全相关的问题时,通常会采用两个非常流行的安全框架,Shiro 和 Spring Security.Shiro 配置简单,上手快,满足一般应用的安全需求,但是功能相对单一.Spring Security 安全粒度细,与 Spring Framework 无缝集成,满足绝大多数企业级应用的安全需求,但是配置复杂,学习曲线陡峭. Spring Security 相对 Shiro 功能强大,并且 Spring Framework,Spring Boot,Sp

随机推荐