0

如何为每个登录的用户创建一个 LoginController bean。问题是新用户登录的那一刻,正在使用相同的登录控制器,唯一改变的是当前用户。

他是我的 LoginController Bean:

@ManagedBean(name = "loginController")

@SessionScoped

@Controller

public class LoginController implements Serializable {

private static final long serialVersionUID = 1L;

@Autowired
IUserService userService;

@Autowired
@Qualifier("authenticationManager")
protected AuthenticationManager authenticationManager;

// save the current user after login to be able to inject it in other places
// as needed
private User currentUser;

private RequestCache requestCache = new HttpSessionRequestCache();

// inject error message strings
@Value("${loginError.title}")
private String loginErrorTitle;

@Value("${loginError.noAccount}")
private String loginErrorNoAccount;

@Value("${loginError.badCredentials}")
private String loginErrorBadCredentials;

@Value("${loginError.accountLocked}")
private String loginErrorAccountLocked;

@Value("${loginError.accountLocked}")
private String loginErrorAccountDisabled;

/**
 * @return the userService
 */
public IUserService getUserService() {
    return userService;
}

/**
 * @param userService
 *            the userService to set
 */
public void setUserService(IUserService userService) {
    this.userService = userService;
}

/**
 * @return the currentUser
 */
public User getCurrentUser() {
    return currentUser;
}

/**
 * @param currentUser
 *            the currentUser to set
 */
public void setCurrentUser(User currentUser) {
    this.currentUser = currentUser;
}

/**
 * This action logs the user in and returns to the secure area.
 * 
 * @return String path to secure area
 */
public void loginUsingSpringAuthenticationManager() {
    // get backing bean for simple redirect form
    LoginFormBackingBean loginFormBean = (LoginFormBackingBean) FacesUtils
            .getBackingBean("loginFormBean");

    try {

        // check if we have the user with the specified username in the DB
        // if we do, authenticate him
        User user = userService.getUserByUsername(loginFormBean
                .getUserName().trim());
        if (null != user) {
            // simple token holder
            Authentication authenticationRequestToken = createAuthenticationToken(loginFormBean);

            Authentication authenticationResponseToken = authenticationManager
                    .authenticate(authenticationRequestToken);

            Authentication authCopy = null;
            final Object principal = authenticationResponseToken
                    .getPrincipal();
            if (principal instanceof LdapUserDetailsImpl) {
                LdapUserDetailsImpl userImpl = (LdapUserDetailsImpl) principal;
                userImpl.getUsername();
                // set the obtained user as the current user
                setCurrentUser(user);
                List<GrantedAuthority> grAuth = new ArrayList<GrantedAuthority>();
                // after this, do the role authority stuff
                // here loop through user roles if he has more and

                // get the highest role for the user and set it as authority
                Role role = userService.getMaxRoleForUser(currentUser);
                grAuth.add(new SimpleGrantedAuthority(role.getName()));

                authCopy = new UsernamePasswordAuthenticationToken(
                        authenticationResponseToken.getPrincipal(),
                        authenticationResponseToken.getCredentials(),
                        grAuth);
            }

            SecurityContextHolder.getContext().setAuthentication(authCopy);
            // ok, test if authenticated, if yes reroute
            if (authenticationResponseToken.isAuthenticated()) {
                // if authentication is successful, get the redirect URL and
                // go to that page;
                // if redirect URL is null -> go to index.xhtml
                HttpServletRequest request = (HttpServletRequest) FacesContext
                        .getCurrentInstance().getExternalContext()
                        .getRequest();

                HttpServletResponse response = (HttpServletResponse) FacesContext
                        .getCurrentInstance().getExternalContext()
                        .getResponse();

                SavedRequest savedRequest = requestCache.getRequest(
                        request, response);
                String savedRedirectUrl = savedRequest != null ? savedRequest
                        .getRedirectUrl() : null;

                FacesContext
                        .getCurrentInstance()
                        .getExternalContext()
                        .redirect(
                                savedRedirectUrl != null ? savedRedirectUrl
                                        : "index.xhtml");

            }
        } else {
            // we have no user with this username yet, show message
            FacesContext.getCurrentInstance().addMessage(
                    null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR,
                            loginErrorTitle, loginErrorNoAccount));
        }
    } catch (BadCredentialsException badCredentialsException) {
        FacesContext.getCurrentInstance().addMessage(
                null,
                new FacesMessage(FacesMessage.SEVERITY_ERROR,
                        loginErrorTitle, loginErrorBadCredentials));
    } catch (LockedException lockedException) {
        FacesContext.getCurrentInstance().addMessage(
                null,
                new FacesMessage(FacesMessage.SEVERITY_ERROR,
                        loginErrorTitle, loginErrorAccountLocked));
    } catch (DisabledException disabledException) {
        FacesContext.getCurrentInstance().addMessage(
                null,
                new FacesMessage(FacesMessage.SEVERITY_ERROR,
                        loginErrorTitle, loginErrorAccountDisabled));
    } catch (IOException e) {
        FacesContext.getCurrentInstance().addMessage(
                null,
                new FacesMessage(FacesMessage.SEVERITY_ERROR,
                        loginErrorTitle, e.getStackTrace().toString()));
    }
}

/**
 * Creates an authentication token from the username and password collected
 * from the login form.
 * 
 * @param loginFormBean
 * @return
 */
private Authentication createAuthenticationToken(
        LoginFormBackingBean loginFormBean) {
    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
            loginFormBean.getUserName(), loginFormBean.getPassword());
    return usernamePasswordAuthenticationToken;
}
}

编辑:

谢谢您的回答。我已经验证了两个登录用户专用的两个 loginController 的哈希码,它们是相同的,所以只创建了一个 logginController。我对JSF和Spring的理解很差。我发布的代码是由另一个开发人员实现的。这里是配置:

<!-- This is where we configure Spring-Security  -->
<security:http pattern="/javax.faces.resource/**" security="none"/>
<security:http auto-config="true">
    <security:intercept-url pattern="/login.xhtml" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
    <security:intercept-url pattern="/**" access="ROLE_EMPLOYEE, ROLE_TEAM_LEADER, ROLE_MANAGER"/>
    <security:intercept-url pattern="/pages/management/" access="ROLE_MANAGER"/>
    <security:intercept-url pattern="/pages/requests/" access="ROLE_EMPLOYEE, ROLE_TEAM_LEADER, ROLE_MANAGER"/>

    <security:form-login login-page="/login.xhtml" 
                    default-target-url="/index.xhtml"
                    always-use-default-target="false" />
    <security:logout logout-url="/j_spring_security_logout"
            logout-success-url="/login.xhtml"
            invalidate-session="true"/>
</security:http>

<security:authentication-manager alias="authenticationManager">
    <security:authentication-provider ref = "authProvider"/>
</security:authentication-manager>

<bean id="authProvider" 
    class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
    <constructor-arg value="infobest.tm" />
    <constructor-arg value="ldap://192.168.1.6:389"/> 
</bean>

您有任何可以帮助我的建议和有用的材料吗?

对不起我糟糕的英语。

4

1 回答 1

1

在这里,您将 JSF bean 管理注释与 Spring bean 管理注释混合在一起。

@ManagedBean(name = "loginController")
@SessionScoped
@Controller

@ManagedBean 本质上,您已经声明了该类将被 JSF via和Spring via用作托管 bean @Controller。本质上,您最终会得到同一个类的两个完全独立的托管实例。JSF 被声明为通过@SessionScoped. Spring 没有任何显式@Scope声明,因此默认为应用程序范围。由于 Spring 托管 bean 显然优先于 JSF 托管 bean,而 EL 将其评估为#{loginController},因此您最终会获得应用程序范围的 Spring 托管 bean 实例。这完全解释了你的具体问题。

现在您了解了原因,解决方案应该足够明显了。使用一个或另一个框架来管理您的 bean 并在其上设置正确的范围。所以,你应该使用

@ManagedBean
@SessionScoped

或者

@Controller
@Scope("session")

不要在同一个类上混用 JSF+Spring bean 管理注解,这只会让你更加困惑。另请注意,托管 bean 名称默认为#{loginController}已经基于 Javabean 命名约定。

于 2013-09-02T11:19:11.773 回答