栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringSecurity学习第二天

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringSecurity学习第二天

SpringSecurity学习第二天 访问控制url匹配

在前面讲解了认证中所有常用配置,主要是对 http.formLogin() 进行操作。

而在配置类中 http.authorizeRequests() 主要是对url进行控制,也就是我们所说的授权(访问控制)在前面讲解了认证中所有常用配置,主要是对 http.formLogin() 进行操作。而在配置类中 http.authorizeRequests() 主要是对url进行控制,也就是我们所说的授权(访问控制)。

http.authorizeRequests() 也支持连缀写法,总体公式为: url 匹配规则.权限控制方法 通过上面的公式可以有很多 url 匹配规则和很多权限控制方法。这些内容进行各种组合就形成了 Spring Security中的授权。在所有匹配规则中取所有规则的交集。配置顺序影响了之后授权效果,越是具体的应该放在前面,越 是笼统的应该放到后面。

anyRequest()

在表示匹配所有的请求。一般情况下此方法都会使用设置全部内容都需要进行认证。

antMatcher()

public C antMatchers(String… antPatterns)

参数是不定向参数,每个参数是一个 ant 表达式,用于匹配 URL规则。

规则如下:
? : 匹配一个字符
* :匹配 0 个或多个字符
** :匹配 0 个或多个目录

放行所有静态资源

.antMatchers("/static/**").permitAll() 

regexMatchers()

使用正则表达式进行匹配。和 antMatchers() 主要的区别就是参数, antMatchers() 参数是 ant 表达式, regexMatchers() 参数是正则表达式。

无论是 antMatchers() 还是 regexMatchers() 都具有两个参数的方法,其中第一个参数都是HttpMethod,表示请求方式,当设置了HttpMethod后表示只有设定的特定的请求方式才执行对应的权限设置。

.antMatchers(HttpMethod.GET,"/login.html").permitAll()

mvcMatchers()

mvcMatchers()适用于配置了 servletPath 的情况。 servletPath 就是所有的 URL 的统一前缀。在 SpringBoot 整合SpringMVC 的项目中可以在 application.properties 中添加下面内容设置 ServletPath

spring.mvc.servlet.path=/名称

在 Spring Security 的配置类中配置 .servletPath() 是 mvcMatchers()返回值特有的方法,antMatchers()和 regexMatchers()没有这个方法。在 servletPath() 中配置了 servletPath 后,mvcMatchers()直接写 SpringMVC 中@RequestMapping()中设置的路径即可。或者直接在前两个匹配器中加上项目路径

.mvcMatchers("/login.html").servletPath("/xxxx").permitAll()
.antMatchers("/xxxx/login.html").permitAll()

内置访问控制方法

Spring Security 匹配了 URL 后调用了 permitAll() 表示不需要认证,随意访问。在 Spring Security 中提供了多种内置控制。

  • permitAll() : permitAll()表示所匹配的 URL 任何人都允许访问。

  • authenticated() : authenticated()表示所匹配的 URL 都需要被认证才能访问。

  • anonymous() : anonymous()表示可以匿名访问匹配的URL。和permitAll()效果类似,只是设置为 anonymous()的 url 会执行 filter 链中

  • denyAll() : denyAll()表示所匹配的 URL 都不允许被访问。

  • rememberMe() : 被“remember me”的用户允许访问

  • fullyAuthenticated() : 如果用户不是被 remember me 的,才可以访问。


角色权限判断

除了之前讲解的内置权限控制。Spring Security 中还支持很多其他权限控制。这些方法一般都用于用 户已经被认证后,判断用户是否具有特定的要求。

  • hasAuthority(String)判断用户是否具有特定的权限,用户的权限是在自定义登录逻辑中创建 User 对象时指定的。hasAnyAuthority(String …)则匹配多个

    在配置类中通过 hasAuthority(“admin”)设置具有 admin 权限时才能访问。例子中admin和normal 就是用户的权限。权限 严格区分大小写。

    AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal”)                     
    
    .antMatchers("/main1.html").hasAuthority("admin")
    
  • hasRole(String) /hasAnyRole(String …): 如果用户具备给定角色就允许访问。否则出现 403

参数取值来源于自定义登录逻辑UserDetailsService实现类中创建User对象时给User赋予的授权在给用户赋予角色时角色需要以:ROLE_开头,后面添加角色名称。例如:ROLE_abc其中abc是角色名,ROLE_是固定的字符开头使用hasRole()时参数也只写 abc 即可。否则启动报错。

return new User("admin",password, AuthorityUtils.
commaSeparatedStringToAuthorityList("admin,normal,ROLE_abc,/main.html"));}
  • hasIpAddress(String) 如果请求是指定的 IP 就运行访问。
.antMatchers("/main1.html").hasIpAddress("127.0.0.1")

自定义403处理方案

spingSeccurity自带的403界面应当被替换,Spring Security 支持自定义权限受限。当用户试图访问无权限资源时会403

新建类实现 AccessDeniedHandler

@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
        httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
        httpServletResponse.setContentType("application/json;charset=utf-8");
        PrintWriter writer = httpServletResponse.getWriter();
        writer.write("{"status":"403","msg":"权限不足,请联系管理员"}");
        writer.flush();//把数据从缓存区输出输出流
        writer.close();
    }
}

修改配置类

配置类中重点添加异常处理器。设置访问受限后交给哪个对象进行处理。
myAccessDeniedHandler 是在配置类中进行自动注入的。

 @Autowired
 private MyAccessDeniedHandler myAccessDeniedHandler;

http.exceptionHandling()
        .accessDeniedHandler(myAccessDeniedHandler);

基于表达式的访问控制

之前学习的登录用户权限判断实际上底层实现都是调用access(表达式),可以通过 access() 实现和之前学习的权限控制完成相同的功能。

.antMatchers("/main1.html").access("hasAnyAuthority('admin,Admin')")
.antMatchers("/main1.html").hasAnyAuthority("admin","Admin")
使用自定义方法

虽然这里面已经包含了很多的表达式(方法)但是在实际项目中很有可能出现需要自己自定义逻辑的情况.判断登录用户是否具有访问当前 URL 权限。

新建接口及实现类

public interface MyService {
    boolean hasPermission(HttpServletRequest request, Authentication authentication);
}
@Service
public class MyServiceImpl implements MyService {
    @Override
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        String uri = request.getRequestURI();
        Object principal = authentication.getPrincipal();
        if(principal instanceof UserDetails){//怎么这两个联系起来了
            UserDetails userDetails = (UserDetails) principal;
            Collection authorities = userDetails.getAuthorities();
            return authorities.contains(new SimpleGrantedAuthority(uri));
        }
        return false;
    }
}

修改配置类

在 access 中通过@bean的id名.方法(参数)的形式进行调用配置类中修改如下:

.anyRequest().access("@myServiceImpl.hasPermission(request,authentication)");
//request我不知道为什么是这个对象名,而不能是htppservletrequest

基于注解的访问控制

在 Spring Security 中提供了一些访问控制的注解。这些注解都是默认是都不可用的,需要通过@EnableGlobalMethodSecurity 进行开启后使用。注解可以写到 Service 接口或方法上,也可以写到 Controller或 Controller 的方法上。通常情况下 都是写在控制器方法上的,控制接口URL是否允许被访问。

开启注解(在启动类 , 也可以在配置类等能够扫描的类上添加)

@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}
  • @Secured

    @Secured 是专门用于判断是否具有角色的。能写在方法或类上。参数要以 ROLE_开头。比如在控制器方法上添加@Secured 注解。也可以传入多个角色,参数是数组类型

    @Secured("ROLE_abc")
    @RequestMapping("/toMain")
    public String toMain(){
       return "redirect:/main.html";
    }
    
  • @PreAuthorize/@PostAuthorize: @PreAuthorize 和@PostAuthorize 都是方法或类级别注解。也需要去配置类中开启注解

    @PreAuthorize 表示访问方法或类在执行之前先判断权限,大多情况下都是使用这个注解,注解
    的参数和access()方法参数取值相同,都是权限表达式。
    @PostAuthorize 表示方法或类执行结束后判断权限,此注解很少被使用到。
    
    @PreAuthorize("hasRole('ROLE_abc')")//可以role可有可无
    @RequestMapping("/toMain")
    public String toMain(){
       return "redirect:/main.html";
    }
    

    拓展:@Secured和@PreAuthorize在Spring Security 3中有什么区别?

    如果你只想在用户具有Role1和Role2的情况下执行某些操作,则必须使用@PreAuthorize,而@Secured中数组元素则是或的关系无法完成共有两角色的限定

    @PreAuthorize("hasRole('ROLE_role1') and hasRole('ROLE_role2')")
    
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/272432.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号