1. 概述
在这个教程中,我们将通过一个简单的场景来演示如何在Spring Security中使用Run-As身份验证。
Run-As的高级解释是:用户可以作为具有不同权限的其他主体执行某些逻辑。
2. RunAsManager
首先,我们需要设置GlobalMethodSecurity
并注入一个RunAsManager
。
这个管理器负责为临时的Authentication
对象提供额外的权限:
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected RunAsManager runAsManager() {
RunAsManagerImpl runAsManager = new RunAsManagerImpl();
runAsManager.setKey("MyRunAsKey");
return runAsManager;
}
}
通过重写runAsManager
,我们替换基础类中的默认实现——它简单地返回null
。
还要注意key
属性——框架使用它来保护和验证通过此管理器创建的临时Authentication
对象。
最后,结果的Authentication
对象是一个RunAsUserToken
。
3. 安全配置
为了验证我们的临时Authentication
对象,我们将设置一个RunAsImplAuthenticationProvider
:
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
...
auth.authenticationProvider(runAsAuthenticationProvider());
}
@Bean
public AuthenticationProvider runAsAuthenticationProvider() {
RunAsImplAuthenticationProvider authProvider = new RunAsImplAuthenticationProvider();
authProvider.setKey("MyRunAsKey");
return authProvider;
}
当然,我们会使用与管理器相同的key
,以便提供商可以检查RunAsUserToken
身份验证对象是否使用相同的key
创建。
4. 使用@Secured的控制器
现在,让我们看看如何使用Run-As身份验证替换:
@Controller
@RequestMapping("/runas")
class RunAsController {
@Secured({ "ROLE_USER", "RUN_AS_REPORTER" })
@RequestMapping
@ResponseBody
public String tryRunAs() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
return "Current User Authorities inside this RunAS method only " +
auth.getAuthorities().toString();
}
}
关键在于新的角色RUN_AS_REPORTER
。这是Run-As功能的触发点,因为框架会因为前缀而以不同的方式处理它。
当请求通过此逻辑执行时,我们将有:
- 在
tryRunAs()
方法调用之前,当前用户的权限是[ROLE_USER]
- 在
tryRunAs()
方法内部,当前用户的权限是[ROLE_USER, ROLE_RUN_AS_REPORTER]
- 临时的
Authentication
对象只在tryRunAS()
方法调用期间替换现有的Authentication
对象
5. 服务层实现
最后,让我们实现实际的逻辑——一个受保护的服务层:
@Service
public class RunAsService {
@Secured({ "ROLE_RUN_AS_REPORTER" })
public Authentication getCurrentUser() {
Authentication authentication =
SecurityContextHolder.getContext().getAuthentication();
return authentication;
}
}
注意:
- 要访问
getCurrentUser()
方法,需要ROLE_RUN_AS_REPORTER
- 因此,我们只能在
tryRunAs()
控制器方法内部调用getCurrentUser()
方法
6. 前端
接下来,我们将使用一个简单的前端来测试Run-As功能:
<html>
<body>
Current user authorities:
<span sec:authentication="principal.authorities">user</span>
<br/>
<span id="temp"></span>
<a href="#" onclick="tryRunAs()">Generate Report As Super User</a>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript">
function tryRunAs(){
$.get( "/runas" , function( data ) {
$("#temp").html(data);
});
}
</script>
</body>
</html>
现在,当用户触发“以超级用户身份生成报告”操作时,他们将获得临时的ROLE_RUN_AS_REPORTER
权限。
7. 总结
在这篇快速教程中,我们探讨了Spring Security中使用Run-As身份验证替换功能的一个简单示例。
本教程基于GitHub上可用的代码库。