一、基于ACCESS方法处理的实现:
我们之前使用的任何放行规则的方法,本质上还是调用access方法执行的
这也意味之我们可以直接使用access方法去方向,只需要注入不同的字符串即可
自定义Access实现:
业务层自定义接口:
package cn.zeal4j.service; import org.springframework.security.core.Authentication; import javax.servlet.http.HttpServletRequest; /** * @author Administrator * @file IntelliJ IDEA Spring-Security-Tutorial * @create 2020 09 28 20:17 */ public interface CustomService { Boolean hasPermission(HttpServletRequest httpServletRequest, Authentication authentication); }
实现类:
package cn.zeal4j.service; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import javax.servlet.http.HttpServletRequest; import java.util.Collection; /** * @author Administrator * @file IntelliJ IDEA Spring-Security-Tutorial * @create 2020 09 28 20:20 */ public class CustomServiceImpl implements CustomService{ @Override public Boolean hasPermission(HttpServletRequest httpServletRequest, Authentication authentication) { // 用户信息对象 Object principal = authentication.getPrincipal(); if (principal instanceof UserDetails) { UserDetails userDetails = (UserDetails) principal; Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities(); return authorities.contains(new SimpleGrantedAuthority(httpServletRequest.getRequestURI())); } return false; } }
Access配置:
package cn.zeal4j.configuration; import cn.zeal4j.handler.CustomAccessDeniedHandler; import cn.zeal4j.handler.FarsAuthenticationFailureHandler; import cn.zeal4j.handler.FarsAuthenticationSuccessHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.access.AccessDeniedHandler; /** * @author Administrator * @file IntelliJ IDEA Spring-Security-Tutorial * @create 2020 09 27 21:55 */ @Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private AccessDeniedHandler accessDeniedHandler; @Bean public PasswordEncoder getPasswordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity.formLogin(). // 设置登陆行为方式为表单登陆 // 登陆请求参数设置 usernameParameter("username"). passwordParameter("password"). loginPage("/login.html"). // 设置登陆页面URL路径 loginProcessingUrl("/login.action"). // 设置表单提交URL路径 // successForwardUrl("/main.page"). // 设置认证成功跳转URL路径 POST请求 successHandler(new FarsAuthenticationSuccessHandler("https://www.acfun.cn/")). // 使用自定义的重定向登陆 // failureForwardUrl("/error.page"); // 设置认证失败跳转URL路径 POST请求 failureHandler(new FarsAuthenticationFailureHandler("/error.html")); // 跨域处理,不需要跳转了 httpSecurity.authorizeRequests(). regexMatchers(HttpMethod.POST, "正则表达式").permitAll(). // 还可以对符合正则表达式的请求方式进行要求,这个属性使用来制定请求的方式 antMatchers("/**/*.js", "/**/*.css", "/**/images/*.*").permitAll(). // 静态资源放行 antMatchers("/login.html").permitAll(). // 登陆页面允许任意访问 antMatchers("/error.html").permitAll(). // 失败跳转后重定向的页面也需要被允许访问 antMatchers("/admin.page").hasAnyAuthority("admin"). /*antMatchers("/vip-01.page").hasAnyAuthority("vip-01").*/ antMatchers("/vip-01.page").hasRole("vip-01"). antMatchers("/ip.page").hasIpAddress("192.168.43.180"). // mvcMatchers("/main.page").servletPath("/xxx").permitAll(). // mvcMatchers资源放行匹配 // antMatchers("/xxx/main.page").permitAll(). // 或者多写MSP的前缀 anyRequest().authenticated(). // 其他请求均需要被授权访问 anyRequest().access("@customServiceImpl.hasPermission(httpServletRequest, authentication)"); // 自定义Access配置 // CSRF攻击拦截关闭 httpSecurity.csrf().disable(); httpSecurity.exceptionHandling().accessDeniedHandler(accessDeniedHandler); } }
这个授权逻辑只允许赋予了对应的接口地址和的才能访问,像默认访问的index页面就会报错
二、@Secured注解:
package org.springframework.security.access.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Secured { String[] value(); }
该注解可以标记的位置,方法和类上面
可以声名的值是一个字符串数组
官方的解释:
用于声名角色权限控制,判断访问此方法是否具备注解中的角色,参数值必须以ROLE_开头
具体使用:
二、@PreAuthorize & @PostAuthorize:
@PreAuthorize 用于在方法或者类之前先判断权限,参数和access方法相同
@PostAuthorize 恰恰相反,在方法和类执行之后判断
使用这些注解需要在启动类中打上@EnableGlobalMethodSecurity
内部字符串会被读取到,和在配置类中设置是差不多的
当然和配置类不同的是,该注解允许方法注入大写的角色权限前缀,例如ROLE_vip-01