简体   繁体   English

Spring 安全 2 种登录方式

[英]Spring Security 2 types of login

I am trying to have a user login and an administrator login.我正在尝试让用户登录和管理员登录。 Currently only the administrator login works and the other one just outputs an error.目前只有管理员登录有效,另一个只是输出错误。 I'm not quite sure why it is not working and if anyone could understand why it is not, could you let me know.我不太确定它为什么不工作,如果有人能理解为什么不工作,你能告诉我。 Here is my security config.这是我的安全配置。

@EnableWebSecurity
public class AdminSecurityConfig extends WebSecurityConfigurerAdapter {
 @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
        .withUser("admin").password("12345").roles("ADMIN")
        .and()
        .withUser("tester").password("56789").roles("ADMIN");
        
    }
    @Override
 protected void configure(HttpSecurity http) throws Exception {
         http.authorizeRequests()
            .antMatchers("/").permitAll()
            .antMatchers("/login")
            .permitAll()
                .antMatchers("/newUser")
                .permitAll()
                .antMatchers("/admin")
                .hasAnyRole("ADMIN")
            .and()
            .formLogin()
            .loginPage("/login1")
            .defaultSuccessUrl("/admin")
            .failureUrl("/login?error=true")
            .permitAll()
                .and()
                .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/login2")
                .defaultSuccessUrl("/success")
                .failureUrl("/login?error==true")
                .permitAll()
                    .and()
                .logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .logoutSuccessUrl("/")
                .deleteCookies("JSESSIONID")
                .invalidateHttpSession(true) 
            .and()
                .csrf()
                .disable()

            ;
  }
         
    @Bean
    public UserDetailsService userDetailsService() {
        return new CustomUserDetailsService();
    }
    @Autowired
    public void configurationGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

And here is the login page for the user - the one that is not working.这是用户的登录页面 - 无法正常工作的页面。

<body id="body">
<div id="container">
<h1>Authorised Users Only</h1>
<div id="box">
<form:form name='user' action="/login2" method='POST'>

             <form:errors path="username" />
    
      <label for="username">Email address</label>
            <input type='text' class="form-control" name='username' value='' placeholder="Enter Email address"></td>
            <label for="password">Password: </label>
            <input type='password' class="form-control" name='password' /></td>
       
        
<input name="submit" class="btn btn-primary" type="submit" value="submit" /></td>
        

</form:form>

So when I type in username = "test" and password = "123" which are correct values it ouputs "error==true".所以当我输入用户名=“测试”和密码=“123”这是正确的值时,它会输出“错误==真”。 Could anyone provide insight into anything that I could do to fix this.任何人都可以提供有关我可以做些什么来解决这个问题的见解。

Here is the requestMapping for "/succsess"这是“/succsess”的requestMapping

    @RequestMapping(value = "/success", method = RequestMethod.GET)
    public String successLogin() {
        return "redirect:/home";
    }
@RequestMapping("/home")
public String homepage( Model model) {
    model.addAttribute("vols", volrepo.findAll());
    return "Homepage";
}

Listing two .formLogin declarations does not do what you are thinking.列出两个.formLogin声明并不符合您的想法。 Instead, you need two separate security configurations.相反,您需要两个单独的安全配置。

If you are using Spring Security 5.4, you can do:如果您使用的是 Spring Security 5.4,您可以执行以下操作:

@Bean
@Order(1)
SecurityFilterChain adminFilters(HttpSecurity http) throws Exception {
    http
        .requestMatchers((matchers) -> matchers.mvcMatchers("/admin/**"))
        .authorizeRequests((requests) -> requests.anyRequest().hasRole("ADMIN"))
        .formLogin((form) -> form
            .defaultSuccessUrl("/admin/home")
            .loginPage("/admin/login").permitAll()
        );

    return http.build();
}

@Bean
@Order(2)
SecurityFilterChain userFilters(HttpSecurity http) throws Exception {
    http
        .authorizeRequests((requests) -> requests.anyRequest().authenticated())
        .formLogin(Customizers.withDefaults());

    return http.build();
}

@Bean
UserDetailsService userDetailsService() { ... }

@Bean
PasswordEncoder passwordEncoder() { ... }

Or, if you are on an earlier version, you can publish two WebSecurityConfigurerAdapter s:或者,如果您使用的是早期版本,则可以发布两个WebSecurityConfigurerAdapter

@Configuration
public class SecurityConfig {
    @Component
    @Order(1)
    static class AdminConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .requestMatchers((matchers) -> matchers.mvcMatchers("/admin/**"))
                .authorizeRequests((r) -> r.anyRequest().hasRole("ADMIN"))
                .formLogin((form) -> form
                    .defaultSuccessUrl("/admin/home")
                    .loginPage("/admin/login").permitAll()
                );

            return http.build();       
        }
    }

    @Component
    @Order(2)
    static class UserConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests((r) -> r.anyRequest().authenticated())
                .formLogin(Customizer.withDefaults());

            return http.build();       
        }
    }

    @Bean
    UserDetailsService userDetailsService() { ... }

    @Bean
    PasswordEncoder passwordEncoder() { ... }
}

Either way, the first filter chain will be invoked for any URL having the pattern /admin/** .无论哪种方式,都会为任何具有/admin/**模式的 URL 调用第一个过滤器链。 If you choose to place all your admin pages in the same path, that makes so that you can have just the one matcher.如果您选择将所有管理页面放在同一路径中,那么您就可以只有一个匹配器。

The second filter chain will be invoked for any other URL.将为任何其他 URL 调用第二个过滤器链。

The UserDetailsService and PasswordEncoder will be shared by both filter chains. UserDetailsServicePasswordEncoder将由两个过滤器链共享。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM