網頁

2019/9/26

Spring Boot Security two form api login範例

本篇介紹如何在Spring Boot Security設定兩個form-data的api登入。


我原本的問題是要在一個Spring Boot應用程式中搭配Spring Security做兩個以form-data api登入,但最終只能透過設定兩個不同的資源路徑來達到此目的,也就是本範例的內容。


先參考「Spring Boot Security form api login範例」建立專案,然後修改Spring Security設定類別DemoWebSecurityConfig如下。

DemoWebSecurityConfig

package com.abc.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@EnableWebSecurity
public class DemoWebSecurityConfig {
    
    @Bean
    public UserDetailsService userDetailsService() {
        
        UserBuilder users = User.withDefaultPasswordEncoder();
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(users
                .username("user123")
                .password("user123")
                .roles("USER").build());
        
        manager.createUser(users
                .username("admin123")
                .password("admin123")
                .roles("USER", "ADMIN")
                .build());
        
        return manager;
    }

    @Configuration
    @Order(1)
    public static class OneLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            
            http
                .antMatcher("/one/**")
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .loginProcessingUrl("/one/login")
                .usernameParameter("username")
                .passwordParameter("password")
                .successHandler( new DemoAuthenticationSuccessHandler() )
                .failureHandler( new DemoAuthenticationFailureHandler() )
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(new DemoAuthenticationEntryPoint())
                .and()
                .csrf()
                .disable();
        }
    }
    
    @Configuration
    @Order(2)
    public static class TwoLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            
            http
                .antMatcher("/two/**")
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .loginProcessingUrl("/two/login")
                .usernameParameter("username")
                .passwordParameter("password")
                .successHandler( new DemoAuthenticationSuccessHandler() )
                .failureHandler( new DemoAuthenticationFailureHandler() )
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(new DemoAuthenticationEntryPoint())
                .and()
                .csrf()
                .disable();
        }
    }
}

重點在一個@EnableWebSecurity類中設定兩個繼承WebSecurityConfigurerAdapter的配置類
OneLoginWebSecurityConfigurerAdapter
TwoLoginWebSecurityConfigurerAdapter
且各別的HttpSecurity.antMatcher()所保護的資源路徑不同。


DemoController新增以下方法測試登入後是否可存取。

DemoController

package com.abc.demo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {
    
    @GetMapping("/")
    public String index() {
        return "Welcome to the home page!";
    }
    
    @PostMapping("/one/resource")
    public String oneResource() {
        return "This is one resource";
    }
    
    @PostMapping("/two/resource")
    public String twoResource() {
        return "This is two resource";
    }
}

開啟Postman,在uri欄位輸入以下並夾帶username/password的form-data皆可登入:

  • POSThttp://localhost:8080/demo/one/login
  • POSThttp://localhost:8080/demo/two/login

KEYVALUE
usernameuser123
passworduser123

登入成功後在uri欄位輸入以下皆可存取:

  • POSThttp://localhost:8080/demo/one/resource
  • POSThttp://localhost:8080/demo/two/resource

參考:

2 則留言:

  1. 大哥請問一下

    我頁面會出現錯誤

    Whitelabel Error Page
    This application has no explicit mapping for /error, so you are seeing this as a fallback.

    Sun Dec 01 19:55:18 CST 2019
    There was an unexpected error (type=Internal Server Error, status=500).
    No serializer found for class com.example.demo.dto.DemoResponse and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)

    回覆刪除
  2. @KJ 你程式有錯誤 檢查一下DemoResponse有沒有寫getter setter

    回覆刪除