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;
}
}
InMemoryAuthenticationProvider
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;
}
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;
}
}
WebSecurityConfigurerAdapter
基本上都是重用了原有的类,很多都是默认使用的,只不过为了修改下行为而重新配置。其实如果偷懒,直接用一个UserDetailsService,在里面做各种认证也是可以的~不过这样就没意思了
spring security 配置多个AuthenticationProvider的更多相关文章
- spring boot 之 spring security 配置
Spring Security简介 之前项目都是用shiro,但是时过境迁,spring security变得越来越流行.spring security的前身是Acegi, acegi 我也玩过,那都 ...
- Spring Security(06)——AuthenticationProvider
目录 1.1 用户信息从数据库获取 1.1.1 使用jdbc-user-service获取 1.1.2 直接使用JdbcDaoImpl 1.2 PasswordEncode ...
- Spring Security 入门(1-4-2)Spring Security - 认证过程之AuthenticationProvider的扩展补充说明
1.用户信息从数据库获取 通常我们的用户信息都不会向第一节示例中那样简单的写在配置文件中,而是从其它存储位置获取,比如数据库.根据之前的介绍我们知道用户信息是通过 UserDetailsService ...
- Spring Security配置个过滤器也这么卷
以前胖哥带大家用Spring Security过滤器实现了验证码认证,今天我们来改良一下验证码认证的配置方式,更符合Spring Security的设计风格,也更加内卷. CaptchaAuthent ...
- Spring学习日志之Spring Security配置
依赖引入 <dependency> <groupId>org.springframework.security</groupId> <artifactId&g ...
- Spring Security配置
更加优雅地配置Spring Securiy(使用Java配置和注解):https://www.cnblogs.com/xxzhuang/p/5960001.html 采用注解方式实现security: ...
- spring mvc 和spring security配置 web.xml设置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmln ...
- 通过 Spring Security配置 解决X-Frame-Options deny 造成的页面空白 iframe调用问题
spring Security下,X-Frame-Options默认为DENY,非Spring Security环境下,X-Frame-Options的默认大多也是DENY,这种情况下,浏览器拒绝当前 ...
- spring mvc 和spring security配置 spring-servlet.xml和spring-security.xml设置
spring-servlet.xml配置 <?xml version="1.0" encoding="UTF-8"?> <beans xmln ...
随机推荐
- spring-AOP-基于Schema切面的小例子
前言: 如果一个项目没有 jdk 5.0 , 那就无法使用基于@AspectJ 注解 的切面. 但是使用AspectJ的表达式的大门还是可以使用的. 我们可以用java提供的Schema配置方法,来替 ...
- Beautils工具类实现的原理
关于内省机制和反射机制请看这一篇博客[还没写完,在草稿中]. 先说一下什么叫做 bean 属性,bean 属性指的是 get / set 方法后的名称,而不是类的属性: 比如: private Str ...
- 序列化与反序列化的单例模式实现和readResolve()
如: public class SingleTest implements Serializable{private static final long serialVersionUID = -860 ...
- 【Egret】WebSocket 的使用说明
在Egret里可以使用WebSocket ,也可以使用socket.io 首先先深入了解一下 WebSocket 在Egret里的机制,看这篇文章: 主要讲解Egret里使用WebSocket和pro ...
- 老李案例分享:MAT分析应用程序服务出现内存溢出过程
老李案例分享:MAT分析应用程序服务出现内存溢出过程 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.在poptest的loa ...
- 老李分享:jvm内存原型剖析
老李分享:jvm内存原型剖析 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:9088214 ...
- Linux开机启动(bootstrap)上
Linux开机启动(bootstrap) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 计算机开机是一个神秘的过程.我们只是 ...
- java调试技能之dubbo调试 ---telnet
dubbo作为一个远程调用框架,虽与同类型的框架,不知道谁优谁劣,但是就公司层面使用来说,还是很棒的.这里简单的写一下怎么使用和调试技巧,就算是作个使用总结吧,供快速使用和问题解决! dubbo是基于 ...
- 设计模式(一)—单例模式
一.概述 1.单例模式的优点 由于单例模式只生成一个实例,减少了系统性能的开销,当一个对象的产生需要比较多的资源时,如读取配置,产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象 ...
- Struts2基础学习(七)—值栈和OGNL
目录: 一.值栈 二.OGNL表达式 一.值栈(ValueStack) 1.定义 ValueStack贯穿整个Acton的生命周期,每个Action类的对象实例都拥有一个ValueStack ...