问题描述
我刚刚查看了许多关于自定义登录页面的示例,每个示例都使用相同的“/login”路径。 经历了这么多的挫折之后,我终于获得了使用默认登录名的权限。
一旦通过身份验证,我希望它转到“/home”。
我假设 POST 仍然使用默认的“/login”?
我已经在 POST 表单“/”(与带有 GET 的表单路径相同)和“/login”上都试过了
现在,当我尝试登录时,它不断将我重定向回与表单相同的“/”。
这里又是基本的API逻辑: 默认登录页面应该在“/”, 表单发布到“/登录”, 登录后的成功网址是“/home”, "/home" 和 "/mama" 是受保护的路由。 注销后,它应该重定向到“/”
我无法通过该应用程序,并且不确定是否缺少任何内容,尽管密码显然没问题,但它仍然显示相同的表单登录信息,就好像我无法通过一样
以下是 WebConfigurerAdapter 文件管理器中解释的路由:
@Configuration
@EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
/*auth.inMemoryAuthentication()
.withUser("appuser").password("1234").roles("HEAD")
.and()
.withUser("Mama").password("Mama").roles("MAMA");*/
}
@Override
/*
* Now we have learnt the basics of Spring Security & Authrization method is completed.
* Lets fix Authentication first!
* Got it to work with hasAuthority & hasAnyAuthority but not with roles,not sure why,but it works atm
*
* */
protected void configure(HttpSecurity http) throws Exception {
//disabled for development
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/mama").hasAuthority("MAMA")
.antMatchers("/home").hasAnyAuthority("HEAD","MAMA")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/").permitAll()
.defaultSuccessUrl("/home")
.usernameParameter("username")
.passwordParameter("password")
.and()
.logout()
.logoutSuccessUrl("/");
}
@Bean
/*
* Returning no op password encoder for Now,as we are not encoding passwords as no registration
* implemented for Prototype. We would need to add the users from a separate service. W
*
* */
public PasswordEncoder getpasswordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
}
//LoginApi:
@RestController
public class LoginApi {
@RequestMapping("/")
public String index(){
return "<form method='POST' action='/login'>" +
"<div>" +
"<input type='text' name='username' placeholder='Username: ' />" +
"</div>" +
"<div>" +
"<input type='password' name='password' placeholder='Password: ' />" +
"</div>" +
"<div>" +
"<input type='submit' name='submit' value='Login' />" +
"</div>" +
"</form>";
}
@RequestMapping("/home")
public String home(){
return "Welcome to Home!";
}
/*
* This method can be deleted in the end
* */
@RequestMapping("/mama")
public String roletest(){
return "This end point is only for Mama!";
}
}
对于这个测试,我没有使用数据库,但我有一个 UserPrincipal 和 UserDetailsService 的工作实现,它在默认登录设置上完美运行。 如果需要,很高兴分享该代码。 但在这一点上,我看不出哪里出了问题。
如果有人想查看 UserDetailsService 和 UserDetails 代码,该代码也已包含在内:
@Service
public class EmployeeDetailsService implements UserDetailsService {
@Override
/*
* First,we are testing the Employee details service,independent of the Database,just to make sure we have this part working,* For the purpose of these prototypes,we wont use password encoder because we are not registering,*
* */
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if (!username.equals("Mama")){
throw new UsernameNotFoundException("You got the wrong Username,should be mama");
}
Employee employee = new Employee();
Role role = new Role();
role.setName("HEAD");
employee
.setUsername(username)
.setPassword("1234")
.setRole(role);
return new EmployeePrincipal(employee);
}
}
public class EmployeePrincipal implements UserDetails {
private Employee employee;
public EmployeePrincipal(Employee employee){
this.employee = employee;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
authorities.add(new SimpleGrantedAuthority(employee.getRole().getName()));
return authorities;
}
@Override
public String getpassword() {
return employee.getpassword();
}
@Override
public String getUsername() {
return employee.getUsername();
}
/*
* Methods below are the rubbish methods,we keep as true for Now
*
* */
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
请参阅来自 Networking 的图片,我不明白发生了什么? POST 请求将 302 重定向回“/”并带有 200 状态代码?
无论凭据是对还是错,这都会发生
任何建议将不胜感激
解决方法
CSRF 需要使用自定义表单来实现,所以为了测试和开发,最好禁用 CSRF
protected void configure(HttpSecurity http) throws Exception {
//Disabled for development
http.authorizeRequests()
.antMatchers("/mama").hasAuthority("MAMA")
.antMatchers("/home").hasAnyAuthority("HEAD","MAMA")
.anyRequest().authenticated()
.and()
.csrf().disable()
.formLogin()
.loginPage("/").permitAll()
.loginProcessingUrl("/login")
.defaultSuccessUrl("/home")
.and()
.logout()
.logoutSuccessUrl("/");
}