Spring Security修炼手册(四)————Security默认表达式的权限控制

        前三章主要讲的是Security对于认证的处理,那么本节,会为大家介绍基于Security默认表达式的权限控制(较为简单,无法满足复杂权限控制及多变的权限规则,后面会介绍基于自定义表达式的权限访问控制,可满足99%的业务场景的需求)。

一、介绍及使用

 直接进入主题,基于默认的表达式权限控制,需要在SecurityConfig中配置,代码如下:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{
	
	@Autowired
	private SecurityProperties securityProperties;
	@Autowired
	private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
	@Autowired
	private MyAuthenticationFailureHandler myAuthenticationFailureHandler;
	@Bean
	public PasswordEncoder passwordEncoder(){
		
		return new BCryptPasswordEncoder();
	}
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		
		http
			.formLogin()
				.loginPage(securityProperties.getToLoginProperties().getLoginProperties().getLoginPage())//用户未认证时,转跳到认证的页面
				.loginProcessingUrl(securityProperties.getToLoginProperties().getLoginProperties().getLoginProcessingUrl())//form中action的地址,也就是处理认证请求的URL	
				.usernameParameter(securityProperties.getToLoginProperties().getLoginProperties().getUsernameParameter())//form中用户名密码的name名
				.passwordParameter(securityProperties.getToLoginProperties().getLoginProperties().getPasswordParameter())
				.defaultSuccessUrl(securityProperties.getToLoginProperties().getLoginProperties().getDefaultSuccessUrl())//认证成功后默认转跳的URL
				.successHandler(myAuthenticationSuccessHandler)
				.failureHandler(myAuthenticationFailureHandler)
		.and()
		.authorizeRequests()
			.antMatchers(securityProperties.getToLoginProperties().getLoginProperties().getLoginPage(),
					     securityProperties.getToLoginProperties().getLoginProperties().getLoginProcessingUrl()).permitAll()
			.antMatchers(HttpMethod.GET,"/vip").hasRole("admin")//默认权限表达式
			.anyRequest().authenticated()
		.and()
			.csrf().disable()
			;
	}
	
	

}

    上面代码的含义是,“/vip”这个URL必须是GET请求,且拥有admin权限的用户才可以访问。接下来我们配置一下UserDetailServer,模拟给用户一个admin权限。

@Component
public class MyUserDetailsServer implements UserDetailsService {

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		// TODO Auto-generated method stub
		if("admin".equals(username)){
			
			throw new RuntimeException("admin禁止登录");
		}
		return new User(username, "$2a$10$ofPkBDUezOJp6Sik63Q/0.QlU8a1itEyzldjSXqfn2nDPqXjN0Ljm", AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
	}

}

    AuthorityUtils是Security提供的一个工具类,我使用的这个方法的功能是将一个以“,”分割的字符串转换成UserDetail中第三个参数所需要的Collection<? extends GrantedAuthority>。

    全部配置好后我们重启项目,登录。可以看到,我是拥有admin这个权限的,按道理说我有权限访问“/vip”,我们访问一下试试。

  

    奇怪?我明明拥有“admin”权限,为什么访问“/vip”确是403,请求被拒绝呢?

二、默认权限表达式源码解析

    第一节中,我们明明可以在Authorites看到当前用户拥有了admin权限,但是却访问被拒绝!这又是为什么呢?下面,我带着大家走一边Security的源码,看一看到底是哪里出现了问题。

    我们依旧在UserdetailsServer中打上断点。

    重启项目,登陆后,访问“/vip”查看断点堆栈信息。我们只看最后一个过滤器,这里我们说过,他会读取我们的SecurityConfig的配置信息,做匹配。我们可以看到虽然我们配置的“/vip”需要的权限是admin,但是框架却自动为我们加上了“ROLE_”的前缀,所以,这就是我们为什么匹配不到,无权限访问的原因。

    我们稍作修改,将UserDetailsServer中的权限加上这个前缀。

我们重启项目,再次访问,可以看到已经有权限了,404是由于我没有写这个页面。

三、自定义异常页面

    在前面的介绍中,无论是403还是404,我们使用的都是提供的默认页面实现,而在我们的实际业务中需要我们使用自己的异常页面,那么怎么配置呢?方法有很多种,比如404页面,我们可以写一个不完全匹配的@RequestMapping 这样由于不完全匹配的优先级是小于完全匹配的优先级的,所以当匹配不到映射的时候就会匹配我们的404了。

    但是我既然单独拿出来写一章,其实完全为了凑字数(一不小心说了实话),那肯定就是有更好的方法的,其实在Spring Boot中,只需要在默认静态资源目录下创建一个与状态码同名的页面,就会在出现异常的时候进入到你的页面中。至于Spring boot的默认资源目录是什么,怎么改,请看我的Spring boot系列博客。

我们访问试一下:

猜你喜欢

转载自my.oschina.net/u/3637243/blog/1822261