• Spring 安全表达式简介


    1.简介

    在本教程中,我们将重点介绍 Spring 安全表达式,以及使用这些表达式的实际示例。

    在查看更复杂的实现(例如 ACL)之前,重要的是要牢牢掌握安全表达式,因为如果使用得当,它们会非常灵活和强大。

    2.Maven依赖

    为了使用 Spring Security,我们需要在pom.xml文件中包含以下部分:

    1. <dependencies>
    2. <dependency>
    3. <groupId>org.springframework.securitygroupId>
    4. <artifactId>spring-security-webartifactId>
    5. <version>5.6.0version>
    6. dependency>
    7. dependencies>

    最新版本可以在这里找到。

    请注意,此依赖项仅涵盖 Spring Security;我们需要为完整的 Web 应用程序添加 s pring-corespring-context

    3.配置

    首先,让我们看一下Java配置。

    我们将扩展WebSecurityConfigurerAdapter以便我们可以选择挂钩到基类提供的任何扩展点:

    1. @Configuration
    2. @EnableAutoConfiguration
    3. @EnableWebSecurity
    4. @EnableGlobalMethodSecurity(prePostEnabled = true)
    5. public class SecurityJavaConfig extends WebSecurityConfigurerAdapter {
    6. ...
    7. }

    当然,我们也可以进行 XML 配置:

    1. "1.0" encoding="UTF-8"?>
    2. <beans:beans ...>
    3. <global-method-security pre-post-annotations="enabled"/>
    4. beans:beans>

    4. 网络安全表达式

    现在让我们探索安全表达式:

    • hasRolehasAnyRole
    • hasAuthorityhasAnyAuthority
    • permitAlldenyAll
    • isAnonymousisRememberMeisAuthenticatedisFullyAuthenticated
    • principalauthentication
    • hasPermission

    4.1。hasRole, hasAnyRole

    这些表达式负责定义对我们应用程序中特定 URL 和方法的访问控制或授权:

    1. @Override
    2. protected void configure(final HttpSecurity http) throws Exception {
    3. ...
    4. .antMatchers("/auth/admin/*").hasRole("ADMIN")
    5. .antMatchers("/auth/*").hasAnyRole("ADMIN","USER")
    6. ...
    7. }

    在上面的示例中,我们指定了对以/auth/开头的所有链接的访问权限,将它们限制为使用角色USER或角色ADMIN登录的用户。此外,要访问以/auth/admin/开头的链接,我们需要在系统中具有ADMIN角色。

    我们可以通过编写以下方式在 XML 文件中实现相同的配置:

    1. <http>
    2. <intercept-url pattern="/auth/admin/*" access="hasRole('ADMIN')"/>
    3. <intercept-url pattern="/auth/*" access="hasAnyRole('ADMIN','USER')"/>
    4. http>

    4.2. hasAuthority, hasAnyAuthority

    Spring 中的角色和权限是相似的。

    主要区别在于角色具有特殊的语义。从 Spring Security 4 开始,任何与角色相关的方法都会自动添加“ ROLE_ ”前缀(如果还没有的话)。

    所以hasAuthority('ROLE_ADMIN')类似于hasRole('ADMIN')因为' ROLE_ '前缀是自动添加的。

    使用权限的好处是我们根本不必使用ROLE_前缀。

    这是一个定义具有特定权限的用户的快速示例:

    1. @Override
    2. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    3. auth.inMemoryAuthentication()
    4. .withUser("user1").password(encoder().encode("user1Pass"))
    5. .authorities("USER")
    6. .and().withUser("admin").password(encoder().encode("adminPass"))
    7. .authorities("ADMIN");
    8. }

    然后我们可以使用这些权威表达:

    1. @Override
    2. protected void configure(final HttpSecurity http) throws Exception {
    3. ...
    4. .antMatchers("/auth/admin/*").hasAuthority("ADMIN")
    5. .antMatchers("/auth/*").hasAnyAuthority("ADMIN", "USER")
    6. ...
    7. }

    正如我们所看到的,我们根本没有在这里提到角色。

    此外,从 Spring 5 开始,我们需要一个PasswordEncoder  bean:

    1. @Bean
    2. public PasswordEncoder passwordEncoder() {
    3. return new BCryptPasswordEncoder();
    4. }

    最后,我们还可以选择使用 XML 配置实现相同的功能:

    1. <authentication-manager>
    2. <authentication-provider>
    3. <user-service>
    4. <user name="user1" password="user1Pass" authorities="ROLE_USER"/>
    5. <user name="admin" password="adminPass" authorities="ROLE_ADMIN"/>
    6. user-service>
    7. authentication-provider>
    8. authentication-manager>
    9. <bean name="passwordEncoder"
    10. class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

    和:

    1. <http>
    2. <intercept-url pattern="/auth/admin/*" access="hasAuthority('ADMIN')"/>
    3. <intercept-url pattern="/auth/*" access="hasAnyAuthority('ADMIN','USER')"/>
    4. http>

    4.3. permitAll, denyAll

    这两个注释也很简单。我们可能允许或拒绝访问我们服务中的某些 URL。

    让我们看一下这个例子:

    1. ...
    2. .antMatchers("/*").permitAll()
    3. ...

    使用此配置,我们将授权所有用户(包括匿名用户和登录用户)访问以“/”开头的页面(例如,我们的主页)。

    我们还可以拒绝访问我们的整个 URL 空间:

    1. ...
    2. .antMatchers("/*").denyAll()
    3. ...

    同样,我们也可以对 XML 进行相同的配置:

    1. <http auto-config="true" use-expressions="true">
    2. <intercept-url access="permitAll" pattern="/*" />
    3. <intercept-url access="denyAll" pattern="/*" />
    4. http>

    4.4. isAnonymous, isRememberMe, isAuthenticated, isFullyAuthenticated

    在本小节中,我们将重点关注与用户登录状态相关的表达式。让我们从一个没有登录到我们页面的用户开始。通过在 Java 配置中指定以下内容,我们将允许所有未经授权的用户访问我们的主页:

    1. ...
    2. .antMatchers("/*").anonymous()
    3. ...

    在 XML 配置中也是如此:

    1. <http>
    2. <intercept-url pattern="/*" access="isAnonymous()"/>
    3. http>

    如果我们想保护网站,以便使用它的每个人都需要登录,我们需要使用isAuthenticated()方法:

    1. ...
    2. .antMatchers("/*").authenticated()
    3. ...

    或者我们可以使用 XML 版本:

    1. <http>
    2. <intercept-url pattern="/*" access="isAuthenticated()"/>
    3. http>

    我们还有两个额外的表达式,isRememberMe()isFullyAuthenticated()。通过使用 cookie,Spring 启用了 remember-me 功能,因此无需每次都登录系统。我们可以在这里阅读更多关于记住我的信息。

    为了向通过记住我功能登录的用户授予访问权限,我们可以使用:

    1. ...
    2. .antMatchers("/*").rememberMe()
    3. ...

    我们也可以使用 XML 版本:

    1. <http>
    2. <intercept-url pattern="*" access="isRememberMe()"/>
    3. http>

    最后,我们服务的某些部分要求用户再次进行身份验证,即使用户已经登录。例如,假设用户想要更改设置或支付信息;在系统的更敏感区域请求手动身份验证是一种很好的做法。

    为此,我们可以指定isFullyAuthenticated() ,如果用户不是匿名用户或记住我的用户,则返回true :

    1. ...
    2. .antMatchers("/*").fullyAuthenticated()
    3. ...

    这是 XML 版本:

    1. <http>
    2. <intercept-url pattern="*" access="isFullyAuthenticated()"/>
    3. http>

    4.5. 主体,身份验证

    这些表达式允许我们分别访问代表当前授权(或匿名)用户的主体对象,以及来自SecurityContext的当前Authentication对象。

    例如,我们可以使用principal来加载用户的电子邮件、头像或任何其他可从登录用户访问的数据。

    身份验证提供有关完整身份验证对象及其授予权限的信息。

    在 Spring Security 中检索用户信息一文中更详细地描述了这两个表达式。

    4.6. hasPermission API

    此表达式已记录在案,旨在成为表达式系统和 Spring Security 的 ACL 系统之间的桥梁,允许我们基于抽象权限指定单个域对象的授权约束。

    让我们看一个例子。想象一下,我们有一项允许合作撰写文章的服务,由一位主编辑决定应该发表作者提出的哪些文章。

    为了允许使用这样的服务,我们可以使用访问控制方法创建以下方法:

    1. @PreAuthorize("hasPermission(#articleId, 'isEditor')")
    2. public void acceptArticle(Article article) {
    3. }

    只有授权用户才能调用该方法,并且需要在服务中拥有isEditor权限。

    我们还需要记住在应用程序上下文中显式配置PermissionEvaluator ,其中customInterfaceImplementation将是实现PermissionEvaluator的类:

    1. <global-method-security pre-post-annotations="enabled">
    2. <expression-handler ref="expressionHandler"/>
    3. global-method-security>
    4. <bean id="expressionHandler"
    5. class="org.springframework.security.access.expression
    6. .method.DefaultMethodSecurityExpressionHandler">
    7. <property name="permissionEvaluator" ref="customInterfaceImplementation"/>
    8. bean>

    当然,我们也可以通过 Java 配置来做到这一点:

    1. @Override
    2. protected MethodSecurityExpressionHandler expressionHandler() {
    3. DefaultMethodSecurityExpressionHandler expressionHandler =
    4. new DefaultMethodSecurityExpressionHandler();
    5. expressionHandler.setPermissionEvaluator(new CustomInterfaceImplementation());
    6. return expressionHandler;
    7. }

    5. 结论

    本文是对 Spring Security Expressions 的全面介绍和指南。

    此处讨论的所有示例都可以在 GitHub 项目上找到

  • 相关阅读:
    【云原生】Docker网络原理及Cgroup硬件资源占用控制
    CAN测量模块总线负载率,你关注了吗?
    c++入门99题21-30
    CSS之复合选择器与伪类选择器
    Luancher和unityLibrary都有build.gradle有什么不同
    清除SAPUI5、SAP Fiori和OData缓存的13种方法
    GIS 分析常用的 7 个地理处理工具
    使用venv创建python虚拟环境
    XAF中XPO与EFCore的探讨
    HTTP状态 400 - 错误的请求:在请求目标中找到无效字符。有效字符在RFC 7230和RFC 3986中定义(Tomcat,非SpringBoot)
  • 原文地址:https://blog.csdn.net/allway2/article/details/126974704