Spring Security 3 - 始终返回错误302

时间:2014-08-18 06:34:53

标签: java spring spring-mvc spring-security

我使用Spring 4创建一个简单的应用程序。最近,我将Spring Security 3添加到项目中,但总是得到错误代码302(因此它总是重定向到主页页面。)

这是我的 SecurityConfig

@Configuration
@EnableWebMvcSecurity
@ComponentScan(basePackages = { "com.moon.repository" })
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().withUser("hello").password("world").roles("USER");
}

@Override
public void configure(WebSecurity web) throws Exception {
    web
    .ignoring().antMatchers("/resources/**", "/views/**");
}

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
            .antMatchers("/","/home").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/home")
            .loginProcessingUrl("/acct/signin")
            .and()
            .logout()
            .permitAll();
}

}

我有一个名为 AccountController 的控制器:

@Controller
@RequestMapping(value = "/acct")
public class AccountController {

private final Logger logger = LoggerFactory.getLogger(AccountController.class);

@RequestMapping(value = "/signin", method = RequestMethod.POST)
public String signin(@RequestParam("username") String username,
        @RequestParam("password") String password) {

    logger.info("======== [username:{0}][password:{1}] ========", username, password);

    if ("error@1.1".equalsIgnoreCase(username)) {
        return "error";
    } else {
        return "demo";
    }
}

}

我的WEB-INF结构:

WEB-INF
----views
--------home.jsp
--------demo.jsp
--------error.jsp

流程如下:

  1. 用户使用http://mylocal:8080/moon =>访问网站它显示 home.jsp
  2. 用户按下登录按钮,弹出一个子窗口,询问用户名和密码=>仍然在 home.jsp
  3. 用户按提交按钮=>我假设它将进入/ acct / signin并返回/ demo,但我在Google Chrome中看到错误302然后再次进入/ home
  4. 有什么想法吗?我被困了整整两天,现在我几乎绝望了......

    非常感谢每个人看看我的问题

    ===================================第一次更新======= ============================

    更新: home.jsp

    中的表单
    <form:form role="form" method="POST" action="acct/signin"
    class="form-signin">
    <div class="row">
        <div class="col-lg-5">
            <input name="username" size="20" type="email"
                class="form-control" placeholder="Email address" required
                autofocus> 
                <input name="password" type="password"
                        class="form-control" placeholder="Password" required>
                    <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
        </div>
    </div>
    </form:form>
    

    ===================================第二次更新======= ============================

    我尝试实现UserDetailsS​​ervice(不使用内存中的auth)但仍然......同样的问题 - 错误302

    AppUserDetailsS​​erviceImpl.java

    @Component
    public class AppUserDetailsServiceImpl implements UserDetailsService {
    
        private final Logger logger = LoggerFactory.getLogger(AppUserDetailsServiceImpl.class);
    
        @Override
        public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
    
            logger.info("loadUserByUsername username=" + username);
            logger.info("======== {} ========",SecurityContextHolder.getContext().getAuthentication());
    
            if (!username.equals("hello")) {
                throw new UsernameNotFoundException(username + " not found");
            }
    
            // creating dummy user details
            return new UserDetails() {
    
                private static final long serialVersionUID = 2059202961588104658L;
    
                @Override
                public boolean isEnabled() {
                    return true;
                }
    
                @Override
                public boolean isCredentialsNonExpired() {
                    return true;
                }
    
                @Override
                public boolean isAccountNonLocked() {
                    return true;
                }
    
                @Override
                public boolean isAccountNonExpired() {
                    return true;
                }
    
                @Override
                public String getUsername() {
                    return username;
                }
    
                @Override
                public String getPassword() {
                    return "world";
                }
    
                @Override
                public Collection<? extends GrantedAuthority> getAuthorities() {
                    List<SimpleGrantedAuthority> auths = new java.util.ArrayList<SimpleGrantedAuthority>();
                    auths.add(new SimpleGrantedAuthority("USER"));
                    return auths;
                }
            };
        }
    

    日志显示:

    [14/08/19 15:16:32:200][INFO ][com.moon.repository.AppUserDetailsServiceImpl][loadUserByUsername](24) loadUserByUsername username=hello
    [14/08/19 15:16:32:200][INFO ][com.moon.repository.AppUserDetailsServiceImpl][loadUserByUsername](25) ======== org.springframework.security.authentication.UsernamePasswordAuthenticationToken@f1e4f742: Principal: com.moon.repository.AppUserDetailsServiceImpl$1@e3dc1b1; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@12afc: RemoteIpAddress: 127.0.0.1; SessionId: 023BC9A8B997ECBD826DD7C33AF55FC7; Granted Authorities: USER ========
    

3 个答案:

答案 0 :(得分:7)

我相信Spring会将您重定向到/home,因为您实际上并未通过登录过程对用户进行身份验证。

  1. 您可以通过http://mylocal:8080/moon返回home.jsp视图
  2. 来访问您的网络应用
  3. 您单击SignIn按钮,提交您的登录表单,因为没有显式声明表单登录,Spring Security将显示用户名和密码提示框,供最终用户输入其凭据
  4. 然后将这些凭据发布到登录处理网址(/acct/signin),您恰好在signin
  5. 中使用AccountController方法进行了映射
  6. 此类控制器无法以Spring方式验证用户身份,但仍通过返回字符串将请求重定向到/demo
  7. /demo路径受到任何未经身份验证的用户的保护(.anyRequest().authenticated()),因为当前用户确实未经身份验证,Spring Security会自动将请求重定向到登录页面
  8. 您最终以/home.loginPage("/home")
  9. 结束

    使用InMemoryUserDetailsManagerConfigurer(请参阅inMemoryAuthentication javadoc),您只能成功登录已配置的凭据。如果您需要完全成熟的身份验证系统,则必须为Spring Security配置提供UserDetailsService实现(通过userDetailsService方法)。


    编辑:在与chialin.lin进行对话之后,似乎缺少的配置是defaultSuccessfulUrl,以便Spring Security知道在经过身份验证后重定向用户的位置。

答案 1 :(得分:0)

为避免必须创建新的简单SuccessHandler,请覆盖过滤器中的successfulAuthentication方法,并在设置chain.doFilter()对象后调用Authentication方法安全背景。

答案 2 :(得分:0)

对我来说,我来自一个稍有不同的用例,但在完全起作用之前,“突然”出现了相同的问题。
我的Setup Spring带有一个ExtJs前端,现在我可以在其中建立一个rest接口。
一切都非常好,然后突然我开始收到 http状态302 响应(WTH?)

由于我通过遵循以下示例通过代码实现:https://octoperf.com/blog/2018/03/08/securing-rest-api-spring-security/
SimpleUrlAuthenticationSuccessHandler 的声明。
请参见 4.4 SecurityConfig ,其中 TokenAuthenticationFilter 是使用类 NoRedirectStrategy 构造的;请参阅 4.1重定向策略

依次在我的 AbstractAuthenticationProcessingFilter 扩展程序中未设置此 NoRedirectStrategy ,它将显示 http 302 响应。