前三章主要讲的是Security对于认证的处理,那么本节,会为你们介绍基于Security默认表达式的权限控制(较为简单,没法知足复杂权限控制及多变的权限规则,后面会介绍基于自定义表达式的权限访问控制,可知足99%的业务场景的需求)。java
直接进入主题,基于默认的表达式权限控制,须要在SecurityConfig中配置,代码以下:app
@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>。ide
所有配置好后咱们重启项目,登陆。能够看到,我是拥有admin这个权限的,按道理说我有权限访问“/vip”,咱们访问一下试试。工具
奇怪?我明明拥有“admin”权限,为何访问“/vip”确是403,请求被拒绝呢?spa
第一节中,咱们明明能够在Authorites看到当前用户拥有了admin权限,可是却访问被拒绝!这又是为何呢?下面,我带着你们走一边Security的源码,看一看究竟是哪里出现了问题。code
咱们依旧在UserdetailsServer中打上断点。orm
重启项目,登录后,访问“/vip”查看断点堆栈信息。咱们只看最后一个过滤器,这里咱们说过,他会读取咱们的SecurityConfig的配置信息,作匹配。咱们能够看到虽然咱们配置的“/vip”须要的权限是admin,可是框架却自动为咱们加上了“ROLE_”的前缀,因此,这就是咱们为何匹配不到,无权限访问的缘由。csrf
咱们稍做修改,将UserDetailsServer中的权限加上这个前缀。ip
咱们重启项目,再次访问,能够看到已经有权限了,404是因为我没有写这个页面。
在前面的介绍中,不管是403仍是404,咱们使用的都是提供的默认页面实现,而在咱们的实际业务中须要咱们使用本身的异常页面,那么怎么配置呢?方法有不少种,好比404页面,咱们能够写一个不彻底匹配的@RequestMapping 这样因为不彻底匹配的优先级是小于彻底匹配的优先级的,因此当匹配不到映射的时候就会匹配咱们的404了。
可是我既然单独拿出来写一章,其实彻底为了凑字数(一不当心说了实话),那确定就是有更好的方法的,其实在Spring Boot中,只须要在默认静态资源目录下建立一个与状态码同名的页面,就会在出现异常的时候进入到你的页面中。至于Spring boot的默认资源目录是什么,怎么改,请看个人Spring boot系列博客。
咱们访问试一下: