前言
发现很少关于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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
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就可以了
1
2
3
4
5
6
7
|
@Bean
DaoAuthenticationProvider daoAuthenticationProvider(){
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setPasswordEncoder( new BCryptPasswordEncoder());
daoAuthenticationProvider.setUserDetailsService(userServiceDetails);
return daoAuthenticationProvider;
}
|
最后在WebSecurityConfigurerAdapter里配置一个含有以上两个AuthenticationProvider的AuthenticationManager,依然重用spring security提供的ProviderManager
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
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,在里面做各种认证也是可以的~不过这样就没意思了
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://www.cnblogs.com/scau-chm/p/6836748.html?utm_source=tuicool&utm_medium=referral