With the help of SpringBeanFacesELResolver
, you can have the managed property Authentication Manager
resolved from the Spring Application Context and JSF's IOC injects the bean to your backing bean.
For this add SpringBeanFacesELResolver to your faces-config.xml like this:
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
and then in your backing bean you can authenticate the passed Authentication object like below:
public class LoginBean implements Serializable {
private static final long serialVersionUID = 1L;
private String userName;
private String password;
@ManagedProperty(value="#{authenticationManager}")
private AuthenticationManager authenticationManager;
public AuthenticationManager getAuthenticationManager() {
return authenticationManager;
}
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
this.authenticationManager= authenticationManager;
}
public String doLogin() {
Authentication authenticationRequestToken =
new UsernamePasswordAuthenticationToken( userName, password );
//authentication action
try {
Authentication authenticationResponseToken =
authenticationManager.authenticate(authenticationRequestToken);
SecurityContextHolder.getContext().setAuthentication(authenticationResponseToken);
//ok, test if authenticated, if yes reroute
if (authenticationResponseToken.isAuthenticated()) {
//lookup authentication success url, or find redirect parameter from login bean
return "/secure/examples";
}
} catch (BadCredentialsException badCredentialsException) {
FacesMessage facesMessage =
new FacesMessage("Login Failed: please check your username/password and try again.");
FacesContext.getCurrentInstance().addMessage(null,facesMessage);
} catch (LockedException lockedException) {
FacesMessage facesMessage =
new FacesMessage("Account Locked: please contact your administrator.");
FacesContext.getCurrentInstance().addMessage(null,facesMessage);
} catch (DisabledException disabledException) {
FacesMessage facesMessage =
new FacesMessage("Account Disabled: please contact your administrator.");
FacesContext.getCurrentInstance().addMessage(null,facesMessage);
}
return null;
}
}
See also:
UPDATE
If you are unable to use the @ManagedProperty for some reason. You can try to use Spring @Autowired annotation by making the JSF ManagedBean into a Spring-managed Component.
For that annotate the bean like this:
@Component
@Scope("request")
public class LoginController implements Serializable {
@Autowired
private AuthenticationManager authenticationManager;
//bean getters and setters
and add component-scan element to your Spring Application context like this:
<context:component-scan base-package="com.examples"/>
For you question regarding using authentication-success-handler-ref, I am afraid you can use that since we are manually doing the authentication. If your requirement is to just forward to appropriate url based of user role. You can do something like this:
if (authenticationResponseToken.isAuthenticated()) {
String userTargetUrl = "/general/main";
String adminTargetUrl = "/secure/examples";
Set<String> roles = AuthorityUtils.authorityListToSet(authenticationResponseToken.getAuthorities());
if (roles.contains("ROLE_ADMIN")) {
return adminTargetUrl;
}
else if(roles.contains("ROLE_USER")) {
return userTargetUrl;
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…