當前我正在使用spring security和@PreAuthorize
註釋來保護方法調用。現在我想改變一個方法調用的認證標記,就像Spring安全允許我做的run-as authentication replacement一樣。用spring-security更改方法調用的安全上下文
我可以在每個方法基礎上配置替換嗎?每註釋,SpEL表達式.... 如果沒有,是否有可能在runAsManager中計算出哪種方法被調用? 我將如何配置安全對象的安全配置屬性?
當前我正在使用spring security和@PreAuthorize
註釋來保護方法調用。現在我想改變一個方法調用的認證標記,就像Spring安全允許我做的run-as authentication replacement一樣。用spring-security更改方法調用的安全上下文
我可以在每個方法基礎上配置替換嗎?每註釋,SpEL表達式.... 如果沒有,是否有可能在runAsManager中計算出哪種方法被調用? 我將如何配置安全對象的安全配置屬性?
我通過實現我自己的RunAsManager
解決了這個問題,它檢查被調用方法上的自定義註釋並返回相應的令牌。
很好用。
我已經發布a detailed article實施運行與@PreAuthorize
結合。
1)實現您自己的RunAsManager
,創建Authentication
以在基於任何自定義邏輯的方法執行期間使用。下面的示例使用自定義註釋提供額外的角色:
public class AnnotationDrivenRunAsManager extends RunAsManagerImpl {
@Override
public Authentication buildRunAs(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
if(!(object instanceof ReflectiveMethodInvocation) || ((ReflectiveMethodInvocation)object).getMethod().getAnnotation(RunAsRole.class) == null) {
return super.buildRunAs(authentication, object, attributes);
}
String roleName = ((ReflectiveMethodInvocation)object).getMethod().getAnnotation(RunAsRole.class).value();
if (roleName == null || roleName.isEmpty()) {
return null;
}
GrantedAuthority runAsAuthority = new SimpleGrantedAuthority(roleName);
List<GrantedAuthority> newAuthorities = new ArrayList<GrantedAuthority>();
// Add existing authorities
newAuthorities.addAll(authentication.getAuthorities());
// Add the new run-as authority
newAuthorities.add(runAsAuthority);
return new RunAsUserToken(getKey(), authentication.getPrincipal(), authentication.getCredentials(),
newAuthorities, authentication.getClass());
}
}
此實現將尋找一個自定義@RunAsRole
標註在受保護的方法(如@RunAsRole("ROLE_AUDITOR")
),如有發現,將添加特定機構(ROLE_AUDITOR
在本案)列入授權機構名單。 RunAsRole
本身只是一個簡單的自定義註釋。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RunAsRole {
String value();
}
2)實例化管理器:
<bean id="runAsManager"
class="org.springframework.security.access.intercept.RunAsManagerImpl">
<property name="key" value="my_run_as_key"/>
</bean>
3)註冊它:
<global-method-security pre-post-annotations="enabled" run-as-manager-ref="runAsManager">
<expression-handler ref="expressionHandler"/>
</global-method-security>
4)實施例的使用在控制器:
@Controller
public class TransactionLogController {
@PreAuthorize("hasRole('ROLE_REGISTERED_USER')") //Authority needed to access the method
@RunAsRole("ROLE_AUDITOR") //Authority added by RunAsManager
@RequestMapping(value = "/transactions", method = RequestMethod.GET) //Spring MVC configuration. Not related to security
@ResponseBody //Spring MVC configuration. Not related to security
public List<Transaction> getTransactionLog(...) {
... //Invoke something in the backend requiring ROLE_AUDITOR
{
... //User does not have ROLE_AUDITOR here
}
編輯: 在RunAsManagerImpl
中的值可以是任何你想要的。下面是Spring docs其使用的摘錄:
爲了確保惡意代碼不會創建一個關鍵的
RunAsUserToken
和現在 它保證接受的RunAsImplAuthenticationProvider
, 散列被存儲在所有生成的標記。該RunAsManagerImpl
和RunAsImplAuthenticationProvider
在 豆上下文中創建具有相同的鍵:<bean id="runAsManager" class="org.springframework.security.access.intercept.RunAsManagerImpl">
<bean id="runAsAuthenticationProvider" class="org.springframework.security.access.intercept.RunAsImplAuthenticationProvider">
通過使用 相同的密鑰,每個
RunAsUserToken
可以驗證它的創建由 批准RunAsManagerImpl
。出於安全原因,創建 之後RunAsUserToken
是不可變的。
「my_run_as_key」的用途是什麼? - 我無法弄清楚。我可能讀過你在這裏引用的同一個指南,但這個關鍵對我沒有任何意義。 – 2016-12-12 11:07:39
@DanielBo值可以是任何你想要的。它基本上是一個密碼。 我更新了爲什麼需要引用Spring文檔的答案。 – kaqqao 2016-12-12 14:34:27