【问题标题】:Authentication using cookies in spring boot在 Spring Boot 中使用 cookie 进行身份验证
【发布时间】:2019-02-08 03:59:24
【问题描述】:

//我的Controller类的一部分

@RequestMapping("/login")
    public String login(HttpServletRequest request,HttpServletResponse response) {
        request.setAttribute("mode", "MODE_LOGIN");


        return "welcomepage";
    }

    @RequestMapping ("/login-user")
    public String loginUser(@ModelAttribute User user, HttpServletRequest request,HttpServletResponse response) {
        if((userService.findByUsernameAndPassword(user.getUsername(), user.getPassword())!=null)) {
            Cookie loginCookie=new Cookie("mouni","user.getUsername()");
            loginCookie.setMaxAge(30*5);
            response.addCookie(loginCookie);
        return "homepage";
        }
        else {
            request.setAttribute("error", "Invalid Username or Password");
            request.setAttribute("mode", "MODE_LOGIN");
            return "welcomepage";

        }

    }

我在 java spring boot 上做一个库管理项目。 我有一个问题,我想使用 cookie 进行身份验证。 简而言之,一旦用户使用其凭据登录后,用户名应保存为 cookie 值。下次用户登录时,输入用户名即可,应该可以登录成功。 有人能帮帮我吗

【问题讨论】:

  • 为什么不考虑使用 Spring Security? spring.io/guides/topicals/spring-security-architecture
  • 您选择自定义控制器而不是使用实际上具有“记住我”功能的 Spring Security 是否有原因?
  • 是的,我必须这样做。这是我的任务。所以请以这种方式指导我。

标签: java spring-boot session-cookies


【解决方案1】:

由于安全性是一个复杂的问题,我建议您使用Spring Security,即使您的任务是不使用它。为了说明安全性的复杂性,我已经可以告诉您,您当前的代码存在漏洞,因为您信任纯文本用户名 cookie 作为您的唯一身份验证。另一方面,Spring Security 使用密钥来生成记住我的 cookie,因此冒充某人要困难得多(除非您知道密钥)。

所以,如果您要使用 Spring Security,您需要做的第一件事就是创建一个 UserDetailsService,它有一个名为 loadByUsername() 的方法。要实现这一点,您可以使用 UserService 并使用 User 构建器来构造 Spring Security 用户对象:

public class MyUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if ("admin".equalsIgnoreCase(username)) {
        return User.builder()
            .username(username)
            // This should contain the hashed password for the requested user
            .password("$2a$10$T5viXrOTIkraRe2mZPyZH.MAqKaR6x38L.rbmRp53yQ8R/cFrJkda")
            // If you don't need roles, just provide a default one, eg. "USER"
            .roles("USER", "ADMIN")
            .build();
    } else {
        // Throw this exception if the user was not found
        throw new UsernameNotFoundException("User not found");
    }
}

请注意,与您原来的UserService.findByUsernameAndPassword() 不同,您不必自己检查密码,只需检索用户对象并传递散列密码即可。

下一步是提供一个合适的PasswordEncoder bean。在我的示例中,我使用了 10 次旋转的 BCrypt,因此我创建了以下 bean:

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(10);
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return new MyUserDetailsService();
    }
}

下一步是配置 Spring Security。例如:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .antMatcher("/**")
        .authorizeRequests()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/login.html").permitAll()
            .loginProcessingUrl("/login-user").permitAll().usernameParameter("username").passwordParameter("password")
            .defaultSuccessUrl("/welcome.html")
            .and()
        .rememberMe()
            .alwaysRemember(true)
            .tokenValiditySeconds(30*5)
            .rememberMeCookieName("mouni")
            .key("somesecret")
            .and()
        .csrf().disable();
}

在这种情况下,所有端点 (/**) 都将受到保护,您将在 login.html 拥有一个登录表单,其中包含两个表单字段(usernamepassword)。表单的目的地应该是/login-user,当用户成功登录后,他将被重定向到/welcome.html

与您在代码中编写的内容类似,这将生成一个名为 mouni 的 cookie,其中包含一个值(不再是普通用户名),它的有效期为 150 秒,就像在您的示例中一样。

我在这里禁用 CSRF 是因为我使用的是简单的 HTML 表单,否则我将不得不添加一个模板引擎来传递 CSRF 密钥。理想情况下,您应该启用此功能。

【讨论】:

    【解决方案2】:

    您正在使用 Spring 框架,该框架具有您想要实现的功能。那为什么要手动呢?

    看看 Spring Security。

    https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/

    【讨论】:

    • 实际上,这样做是任务。这就是为什么我要这样做。
    • 有什么限制不能使用spring security吗?
    • 是的,我只能这样做。
    猜你喜欢
    • 2018-02-08
    • 2018-08-29
    • 2023-03-19
    • 1970-01-01
    • 2018-12-24
    • 2014-09-10
    • 2014-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多