spring 基于请求参数的Spring安全认证
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19791406/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring security authentication based on request parameter
提问by Bing Qiao
The application I'm working on already has Spring Security to handle form based authentication. Now the requirement is to login a user programmatically via an external service ifa token is found in one of the request parameters.
我正在处理的应用程序已经有 Spring Security 来处理基于表单的身份验证。现在的要求是,如果在请求参数之一中找到令牌,则通过外部服务以编程方式登录用户。
In other words, if a particular request parameter, say "token", exists, it needs to call an external service with that token to verify if it's a valid token. If it is then the user will be logged in.
换句话说,如果一个特定的请求参数,比如“令牌”,存在,它需要使用该令牌调用一个外部服务来验证它是否是一个有效的令牌。如果是,则用户将登录。
I can't figure out how and where to "trigger" or "hook on to" Spring Security to check this parameter and make the verification then authenticate the user when appropriate since there is no login form. I thought there should be something in Spring Security that can be extended or customized to do this?
由于没有登录表单,我无法弄清楚如何以及在何处“触发”或“挂钩”Spring Security 来检查此参数并进行验证,然后在适当的时候对用户进行身份验证。我认为 Spring Security 中应该有一些可以扩展或定制的东西来做到这一点?
I looked through Spring Security documentation and wonder if AbstractPreAuthenticatedProcessingFilter is the right thing to start with?
我查看了 Spring Security 文档,想知道 AbstractPreAuthenticatedProcessingFilter 是否适合开始?
回答by Dan
I have a similar setup in my application. Here are the basic elements as far as I can tell:
我的应用程序中有类似的设置。据我所知,以下是基本要素:
You need to create an AuthenticationProvider
like so:
你需要AuthenticationProvider
像这样创建一个:
public class TokenAuthenticationProvider implements AuthenticationProvider {
@Autowired private SomeService userSvc;
@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
if (auth.isAuthenticated())
return auth;
String token = auth.getCredentials().toString();
User user = userSvc.validateApiAuthenticationToken(token);
if (user != null) {
auth = new PreAuthenticatedAuthenticationToken(user, token);
auth.setAuthenticated(true);
logger.debug("Token authentication. Token: " + token + "; user: " + user.getDisplayName());
} else
throw new BadCredentialsException("Invalid token " + token);
return auth;
}
}
You also need to create a Filter
to turn the custom parameter into an authentication token:
您还需要创建一个Filter
以将自定义参数转换为身份验证令牌:
public class AuthenticationTokenFilter implements Filter {
@Override
public void init(FilterConfig fc) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws IOException, ServletException {
SecurityContext context = SecurityContextHolder.getContext();
if (context.getAuthentication() != null && context.getAuthentication().isAuthenticated()) {
// do nothing
} else {
Map<String,String[]> params = req.getParameterMap();
if (!params.isEmpty() && params.containsKey("auth_token")) {
String token = params.get("auth_token")[0];
if (token != null) {
Authentication auth = new TokenAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
}
fc.doFilter(req, res);
}
@Override
public void destroy() {
}
class TokenAuthentication implements Authentication {
private String token;
private TokenAuthentication(String token) {
this.token = token;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return new ArrayList<GrantedAuthority>(0);
}
@Override
public Object getCredentials() {
return token;
}
@Override
public Object getDetails() {
return null;
}
@Override
public Object getPrincipal() {
return null;
}
@Override
public boolean isAuthenticated() {
return false;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
}
@Override
public String getName() {
// your custom logic here
}
}
}
You need to create beans for these:
您需要为这些创建 bean:
<beans:bean id="authTokenFilter" class="com.example.security.AuthenticationTokenFilter" scope="singleton" />
<beans:bean id="tokenAuthProvider" class="com.example.security.TokenAuthenticationProvider" />
Finally, you need to wire these beans into your security config (adjust accordingly):
最后,您需要将这些 bean 连接到您的安全配置中(相应地调整):
<sec:http >
<!-- other configs here -->
<sec:custom-filter ref="authTokenFilter" after="BASIC_AUTH_FILTER" /> <!-- or other appropriate filter -->
</sec:http>
<sec:authentication-manager>
<!-- other configs here -->
<sec:authentication-provider ref="tokenAuthProvider" />
</sec:authentication-manager>
There might be another way, but this definitely works (using Spring Security 3.1 at the moment).
可能还有另一种方式,但这绝对有效(目前使用 Spring Security 3.1)。
回答by nndru
If you use Spring MVC controller or service, where targe request parameter is passed, then you can use @PreAuthorize Spring security annotation.
如果您使用 Spring MVC 控制器或服务,其中传递了 targe 请求参数,那么您可以使用 @PreAuthorize Spring 安全注释。
Say, you have some Spring service that can check passed token and perform authentication if passed token is valid one:
假设您有一些 Spring 服务可以检查传递的令牌并在传递的令牌有效时执行身份验证:
@Service("authenticator")
class Authenticator {
...
public boolean checkTokenAndAuthenticate(Object token) {
...
//check token and if it is invalid return "false"
...
//if token is valid then perform programmatically authentication and return "true"
}
...
}
Then, with Spring security @PreAuthorize annotation you can do this it next way:
然后,使用 Spring security @PreAuthorize 注释,您可以通过以下方式执行此操作:
...
@PreAuthorize("@authenticator.checkTokenAndAuthenticate(#token)")
public Object methodToBeChecked(Object token) { ... }
...
Also, you should enable Spring security annotations by and add spring-security-aspects to POM (or jar to classpath).
此外,您应该启用 Spring 安全注释并将 spring-security-aspects 添加到 POM(或 jar 到类路径)。