亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

盡管已授予權限,Spring Security 仍拒絕訪問“@Secured”方法

盡管已授予權限,Spring Security 仍拒絕訪問“@Secured”方法

森林海 2023-01-05 10:02:50
所以我有一個@Secure為 Spring Security 設計的 Vaadin (8) 視圖:@Secured(SUPERADMIN_ROLE)@SpringView(name = AdminHomeView.NAME)class AdminHomeView : DemoViewWithLabel(){    companion object {        const val NAME = "admin/home"    }    override val labelContent = "This is the protected admin section. You are authenticated and authorized."}哪里DemoViewWithLabel只是一個非常簡單的抽象類顯示VerticalLayout(Label(labelContent))因此,如果我以具有該角色的身份登錄Superadmin,我就可以很好地訪問該視圖。但是,讓我們做一個小改動并覆蓋一個方法......@Secured(SUPERADMIN_ROLE)@SpringView(name = AdminHomeView.NAME)class AdminHomeView : DemoViewWithLabel(){    companion object {        const val NAME = "admin/home"    }    override val labelContent = "This is the protected admin section. You are authenticated and authorized."    override fun enter(event: ViewChangeListener.ViewChangeEvent?) {        super.enter(event)    }}這讓我AccessDeniedException……我不明白為什么。所以我打開了 Spring Security 的 debug loggign,這就是它必須說的:Secure object: ReflectiveMethodInvocation: public void ch.cypherk.myapp.ui.views.admin.AdminHomeView.enter(com.vaadin.navigator.ViewChangeListener$ViewChangeEvent);  target is of class [ch.cypherk.myapp.ui.views.admin.AdminHomeView];  Attributes: [Superadmin]Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@a6801701:  Principal: ch.cypherk.myapp.model.auth.MyUserDetails@6e4c5c5b;  Credentials: [PROTECTED];  Authenticated: true; Details: null;  Granted Authorities: RIGHT_MANAGER, Superadmin 到目前為止,這似乎還可以。它需要一個Superadmin權限,并且它有一個具有該Superadmin權限的經過身份驗證的用戶。
查看完整描述

1 回答

?
梵蒂岡之花

TA貢獻1900條經驗 獲得超5個贊

簡而言之


授予的權限不會顯示ROLE_-prefix,因此會被RoleVoter.


將 替換為RoleVoter具有空前綴的自定義實現解決了該問題。


全文


現在這留下了為什么我們可以訪問視圖的問題。解釋很簡單,但需要更多的上下文。


我們正在努力將 Thorntail 應用程序遷移到 Spring Boot。


我們正在使用 Vaadin 8(因為我們有遺留的 Vaadin 7 東西,我們還沒有設法擺脫它,需要支持)。


所以?


Vaadin 是一個單頁框架,Vaadin 8 有這種討厭的視圖引用方式,即它使用#!根 url(例如https://<host>:<port>/#!foo/bar/baz/...)。


之后什么#都沒有發送到服務器,這意味著我們無法區分訪問/和訪問/#!foo/bar/baz/...


因此,我們不能使用 Spring Security 來保護對視圖的訪問。


并且我們有一個 Vaadin 視圖,我們需要允許未經身份驗證的訪問。


因此,我們被迫允許對/. (MainUI處理所有傳入請求的)將檢查用戶是否已通過身份驗證,如果未通過身份驗證,則重定向到登錄頁面。


對視圖本身的訪問由 Vaadin 保護,而不是 Spring。將SpringViewProvider找不到View用戶無權訪問的內容(因此,用戶無法導航到那里)。


但是,只要我們在該視圖上調用方法,Spring 安全性就會介入并執行訪問檢查。正是這些檢查失敗了,因為授予的權限沒有 Spring 預期的“ROLE_”前綴。(我原以為這只是一個約定,但事實并非如此;RoleVoter實際上忽略了不顯示前綴的權限,因此您必須那樣做,或者您必須提供自己的RoleVoter.)


解決方案相對簡單......


@Configuration

@EnableGlobalMethodSecurity(

    securedEnabled = true,

    prePostEnabled = true,

    proxyTargetClass = true

)

class GlobalSecurityConfiguration : GlobalMethodSecurityConfiguration(){

    override fun accessDecisionManager(): AccessDecisionManager {

        return (super.accessDecisionManager() as AffirmativeBased).apply {

            decisionVoters.replaceAll {

                when(it){

                    is RoleVoter -> MyRoleVoter()

                    else -> it

                }

            }

        }

    }

}

在哪里


class MyRoleVoter : RoleVoter(){

    init {

        rolePrefix = ""

    }

}


查看完整回答
反對 回復 2023-01-05
  • 1 回答
  • 0 關注
  • 172 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號