【问题标题】:Spring Security AuthenticationSuccessHandler and MockMvcSpring Security AuthenticationSuccessHandler 和 MockMvc
【发布时间】:2019-11-02 17:00:22
【问题描述】:

成功认证后,我将认证用户保存在会话中。 之后,我使用 @SessionAttributes("user")

在任何控制器中检索用户

现在我正在尝试测试它:


@ActiveProfiles("test")
@RunWith(SpringRunner.class)
@SpringBootTest(
        webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
        classes = SpringSecurityTestConfig.class
)
public class ProfileMetaDataControllerTest {

    private MockMvc mockMvc;

    @Autowired
    private MyController myController;

    @Autowired
    private WebApplicationContext context;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        this.mockMvc = MockMvcBuilders.standaloneSetup(myController).build();
    }
    @Test
    @WithUserDetails("userMail@hotmail.com")
    public void shouldReturnDefaultMessage() throws Exception {
        String expectedValue ="greeting";
        MvcResult result = this.mockMvc.perform(get("/contentUrl")
                                .contentType(MediaType.TEXT_PLAIN)
                                .content("romakapt@gmx.de"))
                    .andDo(print())
                    .andExpect(content().string(expectedValue))
                    .andReturn();
     }
}

还有我的控制器,它将被测试:

@RestController
@RequestMapping("/profile")
@SessionAttributes("user")
public class ProfileMetaDataController {

    @GetMapping("/contentUrl")
    @ResponseBody
    public List<String> getInformation(Model model) throws IOException {
        User user = Optional.ofNullable((User) model.asMap().get("user")); //User ist null!!!!
    }
}

用户为空,因为我的 AuthenticationSuccessHandler 从不调用 onAuthenticationSuccess 方法,我将用户存储在会话中。

我该如何处理? 通常 UsernamePasswordAuthenticationFilter 会调用我的 AuthenticationSuccessHandler,但不会在 MockMVC 测试期间调用。

【问题讨论】:

    标签: spring-boot spring-security spring-test-mvc


    【解决方案1】:

    如果没有其他原因,请不要使用@SessionAttributes。 通常,Authentication 用户存储在SecurityContextHolder 像这样:

    SecurityContextHolder.getContext().getAuthentication().getPrincipal()
    

    如果您想在控制器上获取用户,请尝试这 3 件事。

    public List<String> getInformation(@AuthenticationPrincipal YourUser youruser) {
        // ...
    }
    
    public List<String> getInformation(Principal principal) {
        YourUser youruser = (YourUser) principal;
        // ...
    }
    
    public List<String> getInformation(Authentication authentication) {
        YourUser youruser = (YourUser) authentication.getPrincipal();
        // ...
    }
    

    【讨论】:

    • 我喜欢@AuthenticationPrincipal 的解决方案,并且我了解SecurityContextHolder。但我不想在每个控制器处理程序方法上写这个语句“SecurityContextHolder.getContext()...”这是将域用户对象放入会话的原因。因为我每次都可以访问这个域对象而无需额外的代码
    猜你喜欢
    • 2014-01-04
    • 2016-07-17
    • 1970-01-01
    • 2016-03-13
    • 2011-11-20
    • 1970-01-01
    • 2011-09-19
    • 1970-01-01
    • 2017-05-12
    相关资源
    最近更新 更多