Bin*_*iao 16 authentication spring spring-security url-parameters
我正在处理的应用程序已经有Spring Security来处理基于表单的身份验证.现在要求是如果在其中一个请求参数中找到令牌,则通过外部服务以编程方式登录用户.
换句话说,如果存在特定的请求参数,例如"令牌",则需要使用该令牌调用外部服务以验证它是否是有效令牌.如果是,那么用户将登录.
我无法弄清楚如何以及在何处"触发"或"挂钩"Spring Security来检查此参数并进行验证,然后在适当时对用户进行身份验证,因为没有登录表单.我认为Spring Security中应该有一些可以扩展或定制的东西来做到这一点?
我浏览了Spring Security文档,想知道AbstractPreAuthenticatedProcessingFilter是否是正确的开始?
Dan*_*Dan 22
我的应用程序中有类似的设置.以下是我能说的基本要素:
你需要创建一个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;
}
}
Run Code Online (Sandbox Code Playgroud)
您还需要创建一个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
}
}
}
Run Code Online (Sandbox Code Playgroud)
您需要为这些创建bean:
<beans:bean id="authTokenFilter" class="com.example.security.AuthenticationTokenFilter" scope="singleton" />
<beans:bean id="tokenAuthProvider" class="com.example.security.TokenAuthenticationProvider" />
Run Code Online (Sandbox Code Playgroud)
最后,您需要将这些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>
Run Code Online (Sandbox Code Playgroud)
可能有另一种方式,但这肯定有效(目前使用Spring Security 3.1).
如果您使用 Spring MVC 控制器或服务,其中传递了 targe 请求参数,那么您可以使用 @PreAuthorize Spring 安全注解。
假设您有一些 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"
}
...
}
Run Code Online (Sandbox Code Playgroud)
然后,使用 Spring security @PreAuthorize 注释,您可以通过以下方式执行此操作:
...
@PreAuthorize("@authenticator.checkTokenAndAuthenticate(#token)")
public Object methodToBeChecked(Object token) { ... }
...
Run Code Online (Sandbox Code Playgroud)
此外,您应该启用 Spring 安全注释并将 spring-security-aspects 添加到 POM(或 jar 到类路径)。
| 归档时间: |
|
| 查看次数: |
19508 次 |
| 最近记录: |