Java 如何在Spring Security中强制重新验证凭据?
我希望在允许在web应用程序中执行特别敏感的操作(例如向一组数据添加签名)之前,强制重新验证凭据 这种情况是,用户已经登录,单击在数据上添加他们的签名,并显示字段以输入他们的凭据,然后将这些凭据传递给服务器进行身份验证。失败不会影响登录状态,只需拒绝操作即可 我正在使用GrailsSpringSecurity插件并根据LDAP(SpringSecurityLDAP)进行身份验证,但我假设解决方案将独立于这些确切的细节Java 如何在Spring Security中强制重新验证凭据?,java,authentication,spring-security,Java,Authentication,Spring Security,我希望在允许在web应用程序中执行特别敏感的操作(例如向一组数据添加签名)之前,强制重新验证凭据 这种情况是,用户已经登录,单击在数据上添加他们的签名,并显示字段以输入他们的凭据,然后将这些凭据传递给服务器进行身份验证。失败不会影响登录状态,只需拒绝操作即可 我正在使用GrailsSpringSecurity插件并根据LDAP(SpringSecurityLDAP)进行身份验证,但我假设解决方案将独立于这些确切的细节 我在服务器端(控制器/servlet)上有用户名和密码值,如何验证这些新凭据?
我在服务器端(控制器/servlet)上有用户名和密码值,如何验证这些新凭据?您可以在控制器中重用用户凭据和
Spring Security
基础结构,而无需操作当前验证。
基本上,您的应用程序通过简单的表单用户名和密码进行请求,并使用authenticationManager
进行验证。根据结果,您可以继续应用程序逻辑或执行其他操作
此示例显示了Spring MVC
控制器中authenticationManager
的用法。
不幸的是,我不是Grails用户。给您一个使用Java和SpringMVC的示例。
为了简洁起见,省略了JSP
可以找到完整的示例(在“批准”页下)
import org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.security.authentication.AuthenticationManager;
导入org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
导入org.springframework.security.core.Authentication;
导入org.springframework.stereotype.Controller;
导入org.springframework.web.bind.annotation.*;
导入org.springframework.web.servlet.ModelAndView;
导入java.util.Map;
@控制器
@请求映射(“批准”)
公共类批准控制器{
@自动连线
私人AuthenticationManager AuthenticationManager;
@RequestMapping(value=“confirm.do”,method=RequestMethod.GET)
公共字符串get(){
返回“批准/确认”;
}
@RequestMapping(value=“confirm.do”,method=RequestMethod.POST)
公共字符串post(@ModelAttribute ApprovalRequestForm表单、映射模型、身份验证){
UsernamePasswordAuthenticationToken=新的UsernamePasswordAuthenticationToken(form.getUsername(),form.getPassword());
Authentication=authenticationManager.authenticate(令牌);
if(authenticate.isAuthenticated()&&isCurrentUser(authentication,authenticate)){
//做你的事
返回“批准/成功”;
}
model.put(“原因”,“凭证不属于当前用户”);
返回“批准/拒绝”;
}
private boolean isCurrentUser(认证左侧,认证右侧){
返回left.getPrincipal().equals(right.getPrincipal());
}
@ExceptionHandler(Exception.class)
公共模型和视图句柄异常(异常){
ModelAndView模型=新的ModelAndView(“批准/拒绝”);
model.addObject(“reason”,exception.getMessage());
收益模型;
}
公共静态类ApprovalRequestForm{
私有字符串用户名;
私有字符串密码;
公共字符串getUsername(){return username;}
public void setUsername(字符串用户名){this.username=username;}
公共字符串getPassword(){return password;}
public void setPassword(字符串密码){this.password=password;}
}
}
我可以在Grails控制器中使用这种方法,只需包括autowired AuthenticationManager,然后根据传入的参数对新令牌进行身份验证。我觉得这很简单,我只是不知道我在做什么。。。谢谢我在这个解决方案中遇到的一个问题是authenticationManager.authenticate(令牌)
将引发运行时异常:AuthenticationException
如果我传递给它的凭据不正确,这意味着我的后续代码将永远不会执行,用户将注销。为了解决这个问题,我必须确保在try/catch中显式地处理任何AuthenticationException
。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.util.Map;
@Controller
@RequestMapping("approval")
public class ApprovalController {
@Autowired
private AuthenticationManager authenticationManager;
@RequestMapping(value="confirm.do", method = RequestMethod.GET)
public String get() {
return "approval/confirm";
}
@RequestMapping(value="confirm.do", method = RequestMethod.POST)
public String post(@ModelAttribute ApprovalRequestForm form, Map<String, Object> model, Authentication authentication) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(form.getUsername(), form.getPassword());
Authentication authenticate = authenticationManager.authenticate(token);
if(authenticate.isAuthenticated() && isCurrentUser(authentication, authenticate)) {
//do your business
return "approval/success";
}
model.put("reason", "credentials doesn't belong to current user");
return "approval/denied";
}
private boolean isCurrentUser(Authentication left, Authentication right) {
return left.getPrincipal().equals(right.getPrincipal());
}
@ExceptionHandler(Exception.class)
public ModelAndView handleException(Exception exception) {
ModelAndView model = new ModelAndView("approval/denied");
model.addObject("reason", exception.getMessage());
return model;
}
public static class ApprovalRequestForm {
private String username;
private String password;
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
}
}