我问了一个关于最新spring框架的问题,基于代码的配置here
初始化
public class AppInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { SecurityConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { MvcConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
mvc config
@EnableWebMvc
@ComponentScan({ "com.appname.controller" })
public class MvcConfig extends WebMvcConfigurerAdapter {
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/res/**").addResourceLocations("/res/");
}
}
安全配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private CustomUserDetailsService customUserDetailsService;
public SecurityConfig() {
customUserDetailsService = new CustomUserDetailsService();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password")
.roles("USER");
auth.userDetailsService(customUserDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/res/**").permitAll()
.and().authorizeRequests()
.anyRequest().hasRole("USER")
.and().formLogin().loginPage("/account/signin").permitAll()
.and().logout().permitAll();
}
}
安全初始值设定项
public class SecurityInitializer extends
AbstractSecurityWebApplicationInitializer {
}
自定义登录
public class CustomUserDetailsService implements UserDetailsService {
private AccountRepository accountRepository;
public CustomUserDetailsService() {
this.accountRepository = new AccountRepository();
}
@Override
public UserDetails loadUserByUsername(String email)
throws UsernameNotFoundException {
Account account = accountRepository.getAccountByEmail(email);
if (account == null) {
throw new UsernameNotFoundException("Invalid email/password.");
}
Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("USER"));
return new User(account.getEmail(), account.getPassword(), authorities);
}
}
但是,现在我有关于自定义登录的新问题。
发布到j_spring_security_check时,我会收到http 302。
我正在请求/,但在登录后,它会停留在登录页面上。
因为我使用的是spring security 4.x版本,以及纯粹基于代码的配置,所以我无法在互联网上找到更多参考资料。任何人都可以帮助弄清楚原因。
修改
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'securityConfig':
Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field:
private org.springframework.security.core.userdetails.UserDetailsService sg.mathschool.infra.SecurityConfig.userDetailsService;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [org.springframework.security.core.userdetails.UserDetailsService] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=userDetailsService)}
我更改了CustomUserDetailsService
@Service("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
private AccountRepository accountRepository;
public CustomUserDetailsService() {
this.accountRepository = new AccountRepository();
}
@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String email)
throws UsernameNotFoundException {
Account account = accountRepository.getAccountByEmail(email);
if (account == null) {
throw new UsernameNotFoundException("Invalid email/password.");
}
Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("USER"));
return new User(account.getEmail(), account.getPassword(), authorities);
}
}
和security config
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("userDetailsService")
private UserDetailsService userDetailsService;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password")
.roles("USER");
auth.userDetailsService(userDetailsService).passwordEncoder(
passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/res/**").permitAll()
.antMatchers("/account/**").permitAll().anyRequest()
.hasRole("USER").and().formLogin().loginPage("/account/signin")
.failureUrl("/account/signin?error").usernameParameter("email")
.passwordParameter("password").and().logout()
.logoutSuccessUrl("/account/signin?logout").and().csrf();
}
@Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
}
答案 0 :(得分:2)
在Spring Security 4.x中,登录网址已更改为login
而不是j_spring_security_check
,请参阅Migrating from Spring Security 3.x to 4.x (XML Configuration)。
<form name='f'action="login" method='POST'>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
<table>
<tbody>
<tr>
<td>User Name</td>
<td><input type="text" name="username" size="30" /></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" name="password" size="30" /></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="login" /></td>
</tr>
</tbody>
</table>
</form>
答案 1 :(得分:1)
是defaultSuccessUrl("/")
formLogin()
...
.defaultSuccessUrl("/")
...
答案 2 :(得分:1)
可能是它的CORS问题? 不管它是什么,你可以通过添加:
来检查请求和响应authentication-success-handler-ref="appLoginSuccessHandler"
authentication-failure-handler-ref="appLoginFailureHandler"
对你的春天安全。
它应该是这样的:
<http use-expressions="true" disable-url-rewriting="true" >
<logout invalidate-session="true" delete-cookies="true"/>
<form-login login-page="/YOUR_login_PAGE"
username-parameter="j_username"
password-parameter="j_password"
login-processing-url="/j_spring_security_check"
authentication-failure-url="/YOUR_login_PAGE"
default-target-url="/YOUR_login_PAGE"
authentication-success-handler-ref="appLoginSuccessHandler"
authentication-failure-handler-ref="appLoginFailureHandler"/>
它将在appLoginSuccessHandler和appLoginFailureHandler服务上调用正确的方法。
服务声明示例:
@Service("appLoginSuccessHandler")
public class LoginSuccessHandler extends
SimpleUrlAuthenticationSuccessHandler{
@Override
public void onAuthenticationSuccess(
HttpServletRequest request, HttpServletResponse response, Authentication
auth) throws IOException, ServletException{ ......
.....
.....
..... Here you can handle also CORS ... and more ...
答案 3 :(得分:0)
请尝试准确指定“loginProcessingUrl”:
formLogin()
...
.loginProcessingUrl("/j_spring_security_check")
...