且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在 Spring Boot 中使用 JWT 身份验证实现基本身份验证?

更新时间:2022-04-10 23:58:05

您将不得不使用不同的根 URL 创建两个不同的 WebSecurityConfigurerAdapter 配置.如果 URL 重叠(即 /admin 和/**),那么您需要在配置上使用 @Order 注释来定义优先级.

You will have to create two different WebSecurityConfigurerAdapter configurations with different root URLs. If the URLs overlap (ie /admin and /**) then you will need to define priority by using @Order annotation on the configuration.

这是 HTTP Basic 和基于表单的身份验证的工作示例.

Here's a working example for HTTP Basic and Form based authentication.

https://github.com/ConsciousObserver/TestMultipleLoginPagesFormAndBasic.git

package com.test;

import javax.servlet.http.HttpSession;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@SpringBootApplication
public class TestMultipleLoginPagesApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestMultipleLoginPagesApplication.class, args);
    }
}

@Controller
class MvcController {
    @RequestMapping(path="form/formLogin", method=RequestMethod.GET)
    public String formLoginPage() {
        return "formLogin";
    }

    @RequestMapping(path="form/formHome", method=RequestMethod.GET)
    public String formHomePage() {
        return "formHome";
    }

    @RequestMapping(path="basic/basicHome", method=RequestMethod.GET)
    public String userHomePage() {
        return "basicHome";
    }

    @RequestMapping(path="basic/logout", method=RequestMethod.GET)
    public String userLogout(HttpSession session) {
        session.invalidate();
        return "basicLogout";
    }
}

@Configuration
@Order(1)
class FormSecurity extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/form/**")
            .authorizeRequests()
                .anyRequest().hasRole("FORM_USER")
            .and()
            .formLogin()
                .loginPage("/form/formLogin").permitAll()
                .loginProcessingUrl("/form/formLoginPost").permitAll()
                .defaultSuccessUrl("/form/formHome")
            .and()
                .logout().logoutUrl("/form/logout").logoutSuccessUrl("/form/formLogin")
            .and()
            .httpBasic().disable()
            .csrf().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("user")
            .password("test")
            .roles("FORM_USER");
    }
}

@Configuration
@Order(2)
class BasicAuthSecurity extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/basic/**")
            .authorizeRequests()
            .anyRequest().hasRole("BASIC_USER")
            .antMatchers("/basic/logout").permitAll()
            .and()
                .httpBasic()
            .and()
                .csrf().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("basic_user")
            .password("test")
            .roles("BASIC_USER");
    }
}

@Configuration
@Order(3)
class RootUrlSecurity extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        /*
         * Put any security expectations from the root URL here, currently everything is permitted.
         * Since it's the last in the order /form/** and /basic/** have a priority over it.
         */
        http.antMatcher("/**")
            .authorizeRequests()
                .anyRequest().permitAll();
    }
}

注意:由于这些登录页面不是来自不同的应用程序,因此它们共享 SecurityContextHolder 或安全上下文.因此,如果您从一个登录页面登录,然后尝试访问另一个的受保护资源,您将不会被重定向到下一个登录页面.相反,您将获得 403(取决于不同登录页面分配的角色).一次只能维持一个登录会话.

Note: Since these login pages are not from different applications, they share the SecurityContextHolder or the security context. So if you login from one login page and then try to go the protected resource of the other, you won't be redirected to the next login page. Instead you'll get the 403 (depending on the roles assigned by the different login pages). At a time only one login session can be maintained.