当前位置: 首页 > 知识库问答 >
问题:

Spring Security 5和JSF 2.2 Bean身份验证

益泰平
2023-03-14

我必须使用jsf配置Spring Security 5,此下面的代码在Spring Security 4中工作正常,但当我迁移到版本5时,身份验证过程不会触发:

登录表单如下所示:

<h:form id="loginForm" prependId="false">
    <p:messages autoUpdate="true" showDetail="false" showSummary="true" showIcon="false" />
    <div class="ui-fluid">
        <p:panelGrid columns="1" layout="grid" styleClass="ui-panelgrid-blank">
            <h:outputLabel for="username" value="#{msg['login.login']}" />
            <p:inputText id="username" value="#{userBean.userDTO.username}" required="true" requiredMessage="#{msg['login.login.required']}" label="#{msg['login.login']}" />

            <h:outputLabel for="password" value="#{msg['login.password']}" />
            <p:password id="password" required="true" feedback="false" label="#{msg['login.password']}" requiredMessage="#{msg['login.password.required']}" />
            <p:spacer />
            <p:commandButton type="submit" value="#{msg['login.btn']}" action="#{userBean.doLogin}" ajax="false" />
        </p:panelGrid>
    </div>
</h:form>

JSF Bean:

public String doLogin() throws ServletException, IOException {
    ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
    RequestDispatcher dispatcher = ((ServletRequest) context.getRequest()).getRequestDispatcher("/login");
    dispatcher.forward((ServletRequest) context.getRequest(), (ServletResponse) context.getResponse());
    FacesContext.getCurrentInstance().responseComplete();
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (auth != null && !(auth instanceof AnonymousAuthenticationToken) && auth.isAuthenticated()) {
        logDebug(LOGGER, getPartCodeLoggedPartner(), "Authentification");
        UserSecurity userSecurity = (UserSecurity) ((Authentication) auth).getPrincipal();
        setUserRight(getLoggedUser(), userSecurity);
    }
    return "";
}

以及安全配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /** The utilisateur service. */
    @Autowired
    private UserDetailsService utilisateurService;

    /*
     * (non-Javadoc)
     * 
     * @see org.springframework.security.config.annotation.web.configuration.
     * WebSecurityConfigurerAdapter#configure(org.springframework.security.
     * config.annotation.web.builders.HttpSecurity)
     */

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // require all requests to be authenticated except for the resources
        http.authorizeRequests().antMatchers("/javax.faces.resource/**", "/resources/**", "/index.jsp", "/views/login.jsf", "/pages/public/**").permitAll().anyRequest().authenticated();
        // login
        http.formLogin().loginPage("/views/login.jsf").loginProcessingUrl("/login").usernameParameter("username").passwordParameter("password").failureUrl("/views/login.jsf?error=true")
                .defaultSuccessUrl("/views/home.jsf");
        // logout
        http.logout().logoutUrl("/logout").invalidateHttpSession(true).logoutSuccessUrl("/views/login.jsf");
        // not needed as JSF 2.2 is implicitly protected against CSRF
        http.csrf().disable();
    }

    /**
     * Md 5 password encoder.
     *
     * @return the message digest password encoder
     */
    @Bean
    public MessageDigestPasswordEncoder md5PasswordEncoder() {
        return new MessageDigestPasswordEncoder("MD5");
    }

    /**
     * Configure global.
     *
     * @param auth
     *            the auth
     * @throws Exception
     *             the exception
     */
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        // Setting Service to find User in the database.
        // And Setting PassswordEncoder
        auth.userDetailsService(utilisateurService).passwordEncoder(md5PasswordEncoder());

    }
}

当我提交登录表单时,身份验证未被触发!我在这个配置中忘记了什么吗?

在Spring Security 4中,触发登录和注销的操作如下所示:

            ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
            RequestDispatcher dispatcher = ((ServletRequest) context.getRequest()).getRequestDispatcher("/j_spring_security_login");
            dispatcher.forward((ServletRequest) context.getRequest(), (ServletResponse) context.getResponse());
            FacesContext.getCurrentInstance().responseComplete();

和注销:

            ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
            RequestDispatcher dispatcher = ((ServletRequest) context.getRequest()).getRequestDispatcher("/j_spring_security_logout");
            dispatcher.forward((ServletRequest) context.getRequest(), (ServletResponse) context.getResponse());
            FacesContext.getCurrentInstance().responseComplete();
            context.invalidateSession();

我尝试将j_spring_security_登录改为登录,将j_spring_security_注销改为注销,但不起作用

共有2个答案

戚育
2023-03-14

我知道这很古老,但我在Spring boot安全性和JSF方面遇到了同样的问题。

基于@molhorm回答,你只需声明过滤链即可转发!

把这个放在你的web.xml

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>
        org.springframework.web.filter.DelegatingFilterProxy
    </filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

它应该会起作用。

融宏伟
2023-03-14

我认为问题可能是Spring Security 5过滤器链不再具有用于转发的默认调度程序映射。我没有找到一种简单的方法在Java配置中添加这个映射,所以我最终直接在doLogin方法中使用authenticationProvider来修复它。

替换:

RequestDispatcher requestDispatcher = ((ServletRequest) externalContext.getRequest()).getRequestDispatcher("/login");
requestDispatcher.forward((ServletRequest) externalContext.getRequest(), (ServletResponse) externalContext.getResponse());
FacesContext.getCurrentInstance().responseComplete();

有了这个:

try {
    UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( username, password ); 
    Authentication authentication = authenticationProvider.authenticate(authenticationToken);
    SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (Exception e) {
    LOGGER.error("Login failed");
    SecurityContextHolder.getContext().setAuthentication(null);
}

    authentication.isAuthenticated()...
 类似资料:
  • 问题内容: 确保GWT + Tomcat应用程序执行身份验证和授权的最佳策略是什么? 问题答案: 有两种基本策略: 确保入口点; 保护远程服务。 最简单的方法是使用常规的Web应用程序安全工具来限制对GWT生成的html / js文件的访问: 春季安全; web.xml约束。 这样可以让您拥有eg 和。 保护远程服务 如果上述解决方案还不够,您可以进行更深入的研究。我已经通过Spring Secu

  • 我有一个REST服务,它依赖于外部系统来验证令牌,但需要自己进行授权(使用like@Secured进行API级访问)。 要求: UI使用外部系统生成令牌 一种可能的解决方案是使用过滤器: > UI使用外部系统生成令牌 UI使用令牌对我的服务进行REST调用 我的服务有一个过滤器,它使用令牌调用外部系统 有效令牌的外部系统发回用户详细信息 我对成功呼叫集的服务与SecurityContextHold

  • 身份验证 PDF版下载 企业应用中的URL链接可以通过OAuth2.0验证接口来获取员工的身份信息。 通过此接口获取员工身份会有一定的时间开销。对于频繁获取员工身份的场景,建议采用如下方案: 企业应用中的URL链接直接填写企业自己的页面地址; 员工跳转到企业页面时,企业校验是否有代表员工身份的cookie,此cookie由企业生成; 如果没有获取到cookie,重定向到OAuth验证链接,获取员工

  • 问题内容: 我正在使用Spring 3 Web应用程序,因为Spring 3不支持NTLM身份验证,可以与Spring安全性一起使用的其他替代方法有哪些?这样,当用户登录到Active Directory时就可以通过应用程序进行身份验证了吗? 目前,Kerberos解决方案不是一个选择,NTLM是唯一的选择。 任何帮助都是非常明显的。 谢谢 问题答案: 我已经做过一次了。在这里抓住它。它将需要在A

  • 几天没有任何进展,我需要你的帮助。 使用GWT,我试图与REST服务器通信,服务器位于不同的URL上(需要CORS)<我的配置:服务器spring boot 1.3.3 客户端-GWT 1.7-restygwt 2.0.3 当我在Spring中禁用安全性时,我可以在我的GWT客户端中获取数据。 但是当我启用它时,我总是收到401个请求。REST URL请求直接在Web浏览器中工作(带有其身份验证对

  • 我正在尝试使用Firebase验证Vue.js应用程序。 我有一个问题,如果在登录时尝试直接访问受登录保护的URL,路由器将在firebase之前加载并检查身份验证状态。js有时间返回auth响应。这会导致用户被弹回登录页面(当他们已经登录时)。 如何延迟vue-router导航直到从Firebase检索到auth状态?我可以看到Firebase将auth数据存储在local存储中,检查它是否作为

  • 我试图为AWS实现“开发人员身份验证身份”,如下所示:https://AWS.amazon.com/blogs/mobile/amazon-cognito-innecling-developer-authenticated-identities/ 我很好地理解了基本流程。 我怎样才能做到这一点?

  • 问题内容: 我正在尝试在Node.js中使用Socket.IO,并试图允许服务器为每个Socket.IO客户端赋予一个身份。由于套接字代码不在http服务器代码的范围内,因此无法轻松访问已发送的请求信息,因此我假设在连接期间需要将其发送出去。什么是最好的方法 1)将有关谁通过Socket.IO连接到服务器的信息 2)验证他们说的是谁(如果正在使事情变得更容易,我目前正在使用Express) 问题答