我使用 Spring 4 创建一个简单的应用程序。最近,我将 Spring Security 3 添加到项目中,但总是得到错误代码 302(所以它总是重定向到 home 页面)。
这是我的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 :
@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
流程是这样的:
- 用户使用
http://mylocal:8080/moon
访问网站 => 它显示 home.jsp - 用户按下按钮 SignIn 并弹出一个子窗口要求输入用户名和密码 => 仍在 home.jsp
- 用户按下提交按钮 => 我认为它会转到/acct/signin 并返回到/demo,但我在 Google Chrome 中看到错误 302,然后它又转到/home
有什么想法吗?我被困了整整两天,现在我几乎绝望了......
非常感谢大家看我的问题
==================================== 第一次更新======= =============================
更新: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>
===================================== 第二次更新======= =============================
我尝试实现 UserDetailsService(不使用内存身份验证),但仍然...同样的问题 - 错误 302
AppUserDetailsServiceImpl.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 ========
最佳答案
我相信 Spring 会将您重定向到 /home
,因为您实际上并未通过登录过程对用户进行身份验证。
- 您通过返回 home.jsp View 的
http://mylocal:8080/moon
访问您的网络应用程序 - 单击登录按钮,提交登录表单
由于没有明确声明表单登录,Spring Security 将显示用户名和密码提示框,供最终用户输入其凭据 - 然后将这些凭据发布到登录处理 URL (
/acct/signin
),您恰好在中与
signin
方法进行了映射AccountController - 这样的 Controller 无法通过 Spring 方式对用户进行身份验证,但仍然通过返回字符串将请求重定向到
/demo
/demo
路径对任何未经身份验证的用户都是 protected (.anyRequest().authenticated()
),由于当前用户确实未经身份验证,Spring Security 会自动将请求重定向到登录页面- 您最终会访问
/home
(.loginPage("/home")
)
使用 InMemoryUserDetailsManagerConfigurer (参见 inMemoryAuthentication javadoc),您只能通过配置的凭据成功登录。如果您想要一个成熟的身份验证系统,您必须提供 UserDetailsService实现 Spring Security 配置(通过 userDetailsService 方法)。
编辑:在与 chialin.lin 交谈之后,似乎缺少的配置是 defaultSuccessfulUrl让 Spring Security 知道一旦通过身份验证将用户重定向到哪里。
关于java - Spring Security 3 - 总是返回错误 302,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25357518/