Spring Security 表達(dá)式 Expressions 詳解

1. 介紹

  • 本文主要是關(guān)注于Spring Security的表達(dá)式。會(huì)有很多案例給大家演示一下怎么使用這些表達(dá)式
  • 掌握了Spring Security表達(dá)式,會(huì)讓你很靈活地實(shí)現(xiàn)復(fù)雜的ACL控制規(guī)則

2. Maven 依賴(lài)

  • 想要使用Spring Security,你需要再pom.xml中加入以下的內(nèi)容。
<dependencies>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
        <version>4.1.1.RELEASE</version>
    </dependency>
</dependencies>
  • 最新的版本可以點(diǎn)擊這里查看

  • 溫馨提示:這里只是包含了Spring Security的依賴(lài),不要忘記把spring-corespring-context的依賴(lài)都加進(jìn)去

3. 配置

  • 首先,我們先新建一個(gè)Java配置類(lèi)SecurityWithoutCsrfConfig

  • 該類(lèi)需要繼承WebSecurityConfigurerAdapter,這里我們就可以使用該基類(lèi)所提供的方法。具體代碼如下:

@Configuration
@EnableAutoConfiguration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityWithoutCsrfConfig extends WebSecurityConfigurerAdapter {
    ...
}
  • 我們也可以通過(guò)XML的方式進(jìn)行配置,不過(guò)不推薦。實(shí)例代碼如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans ...>
    <global-method-security pre-post-annotations="enabled"/>
</beans:beans>

4. 表達(dá)式講解

  • 下面是我們可能會(huì)用到的表達(dá)式:

hasRole, hasAnyRole
hasAuthority, hasAnyAuthority
permitAll, denyAll
isAnonymous, isRememberMe, isAuthenticated, isFullyAuthenticated
principal, authentication
hasPermission

  • 接下來(lái)我們回詳細(xì)地介紹每個(gè)表達(dá)式的使用。

4.1. hasRole, hasAnyRole

  • 這些表達(dá)式負(fù)責(zé)定義應(yīng)用程序中特定URL或方法的訪問(wèn)控制或授權(quán)。
  • 下面是具體的寫(xiě)法:
@Override
protected void configure(final HttpSecurity http) throws Exception {
    ...
    .antMatchers("/auth/admin/*").hasRole("ADMIN")
    .antMatchers("/auth/*").hasAnyRole("ADMIN","USER")
    ...
}
  • 在此示例中,我們指定對(duì)以/auth/開(kāi)頭的所有鏈接進(jìn)行訪問(wèn)權(quán)限的限制,只有角色USER或角色ADMIN登錄的用戶(hù)有訪問(wèn)權(quán)限。此外,要訪問(wèn)以/auth/admin/開(kāi)頭的鏈接,我們需要在系統(tǒng)中具有ADMIN角色。

  • 在XML中可以進(jìn)行一下的配置:

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

4.2. hasAuthority, hasAnyAuthority

  • RolesAuthoritiesSpring中是很相似的

  • 主要區(qū)別在于,角色具有特殊的語(yǔ)義 - 從Spring Security 4開(kāi)始,任何與角色相關(guān)的方法都會(huì)自動(dòng)添加ROLE_前綴。

  • hasAuthority('ROLE_ADMIN')類(lèi)似于hasRole('ADMIN'),因?yàn)?code>ROLE_前綴會(huì)自動(dòng)添加。

  • 我們使用authorities來(lái)賦予用戶(hù)權(quán)限的時(shí)候,比較大的好處是我們不必使用ROLE_前綴。

  • 下面示例是使用authorities的代碼

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
      .withUser("user1").password("user1Pass").authorities("USER")
      .and().withUser("admin").password("adminPass").authorities("ADMIN");
}
  • 我們可以使用一下authorities表達(dá)式來(lái)限定權(quán)限
@Override
protected void configure(final HttpSecurity http) throws Exception {
    ...
    .antMatchers("/auth/admin/*").hasAuthority("ADMIN")
    .antMatchers("/auth/*").hasAnyAuthority("ADMIN", "USER")
    ...
}
  • 我們可以看到,這里是沒(méi)有出現(xiàn)到roles相關(guān)的配置。
  • 可以通過(guò)一下方式來(lái)配置XML文件。
<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="user1" password="user1Pass" authorities="ROLE_USER"/>
            <user name="admin" password="adminPass" authorities="ROLE_ADMIN"/>
        </user-service>
    </authentication-provider>
</authentication-manager>
<http>
    <intercept-url pattern="/auth/admin/*" access="hasAuthority('ADMIN')"/>
    <intercept-url pattern="/auth/*" access="hasAnyAuthority('ADMIN','USER')"/>
</http>

4.3. permitAll, denyAll

  • 這是兩個(gè)比較簡(jiǎn)單的方法,要么就是拒絕指定的所有請(qǐng)求,要么就是允許指定的所有請(qǐng)求。

  • 示例:

...
.antMatchers("/*").permitAll()
...
  • 使用此配置,我們將授權(quán)所有用戶(hù)(匿名用戶(hù)和登錄用戶(hù))訪問(wèn)以'/'開(kāi)頭的頁(yè)面。

  • 我們也可以拒絕訪問(wèn)整個(gè)網(wǎng)站,代碼如下:

...
.antMatchers("/*").denyAll()
...
  • 以下的XML配置可以達(dá)到同樣的效果。
<http auto-config="true" use-expressions="true">
    <intercept-url access="permitAll" pattern="/*" /> <!-- Choose only one -->
    <intercept-url access="denyAll" pattern="/*" /> <!-- Choose only one -->
</http>

4.4. isAnonymous, isRememberMe, isAuthenticated, isFullyAuthenticated

  • 在本小節(jié)中,我們將重點(diǎn)關(guān)注與用戶(hù)登錄狀態(tài)相關(guān)的表達(dá)式。我們從沒(méi)有登錄頁(yè)面的用戶(hù)開(kāi)始。通過(guò)在Java配置中指定以下內(nèi)容,我們?cè)试S所有未經(jīng)授權(quán)的用戶(hù)訪問(wèn)我們的主頁(yè):
...
.antMatchers("/*").anonymous()
...
  • XML配置如下:
<http>
    <intercept-url pattern="/*" access="isAnonymous()"/>
</http>
  • 如果希望訪問(wèn)網(wǎng)站的都需要登錄,那么我們可以使用isAuthenticated()方案進(jìn)行以下的配置:
...
.antMatchers("/*").authenticated()
...
  • or XML version:
  • XML版本如下:
<http>
    <intercept-url pattern="/*" access="isAuthenticated()"/>
</http>
  • 此外,我們還有兩個(gè)表達(dá)式,isRememberMe()和isFullyAuthenticated()。通過(guò)使用cookie,Spring可以實(shí)現(xiàn)存儲(chǔ)功能,因此無(wú)需每次都登錄系統(tǒng)。
  • 為了能夠訪問(wèn)僅通過(guò)記住我的功能登錄的用戶(hù),我們可以使用:
...
.antMatchers("/*").rememberMe()
...
  • XML版本如下:
<http>
    <intercept-url pattern="*" access="isRememberMe()"/>
</http>
  • 最后,即使用戶(hù)已經(jīng)登錄,我們有時(shí)候想要求用戶(hù)再次進(jìn)行身份驗(yàn)證。例如,用戶(hù)想要更改設(shè)置或付款信息。

  • 為了做到這一點(diǎn),我們可以指定isFullyAuthenticated(),如果用戶(hù)不是匿名用戶(hù)或記住我的用戶(hù),則返回true:

...
.antMatchers("/*").fullyAuthenticated()
...
  • XML版本
<http>
    <intercept-url pattern="*" access="isFullyAuthenticated()"/>
</http>

4.5. principal, authentication

  • 這些表達(dá)式允許分別從SecurityContextrespectively表示當(dāng)前授權(quán)(或匿名)用戶(hù)的principal對(duì)象和當(dāng)前的Authentication對(duì)象

  • 例如,我們可以使用委托人來(lái)加載用戶(hù)的電子郵件,頭像或登錄用戶(hù)可訪問(wèn)的任何其他數(shù)據(jù)。

  • 身份驗(yàn)證提供有關(guān)完整身份驗(yàn)證對(duì)象的信息及其授予的權(quán)限

4.6. hasPermission APIs

  • 如表達(dá)式已經(jīng)設(shè)置在了Spring Security的ACL系統(tǒng)中,系統(tǒng)是允許我們根據(jù)抽象權(quán)限指定對(duì)各個(gè)域?qū)ο蟮氖跈?quán)約束。

  • 讓我們來(lái)看一個(gè)例子。我們有一項(xiàng)服務(wù),允許合作撰寫(xiě)文章,與主編輯,決定其他作者提出的文章應(yīng)該發(fā)表

  • 為了允許使用此類(lèi)服務(wù)??,我們可以使用訪問(wèn)控制方法創(chuàng)建以下方法:

@PreAuthorize("hasPermission(#articleId, 'isEditor')")
public void acceptArticle(Article article) {
   …
}
  • 只有授權(quán)的用戶(hù)可以在服務(wù)中調(diào)用此方法
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容