3

@AuthenticationPrincipal オブジェクトは、セッションに保存された以前の値を返します。

スプリング ブート + スプリング セキュリティ oauth REST サーバー。https://github.com/legshort/spring-boot-sample

これら 2 つの REST メソッドはコントローラーにあります。問題は、最後の引数である deleteUser() の userDetailsImpl が、テスト コードを実行したときに updateUser() の userDetailsImpl と同じ値であることです。

@RequestMapping(method = RequestMethod.PUT, value = "/users/{userId}")
public ResponseEntity updateUser(@PathVariable Long userId,
        @AuthenticationPrincipal UserDetailsImpl userDetailsImpl,
        @Valid @RequestBody UserUpdateForm userUpdateForm,
        BindingResult bindingResult) {
    logger.info("UserUpdate: " + userUpdateForm);

    User updatedUser = userService.updateUser(userUpdateForm
            .createUser(userId));

    return new ResponseEntity(updatedUser, HttpStatus.OK);
}

@RequestMapping(method = RequestMethod.DELETE, value = "/users/{userId}")
public ResponseEntity deleteUser(@PathVariable Long userId,
        @AuthenticationPrincipal UserDetailsImpl userDetailsImpl) {
    logger.info("UserDelete: " + userId);

    User requestedUser = new User(userId);
    userService.deleteUser(requestedUser);

    return new ResponseEntity(HttpStatus.NO_CONTENT);
}

以下はコントローラーのテストコードです

方法はわかりませんが、testDeleteUser() である 2 番目のリクエストにはセッション値があり、以前のテストを使用したのと同じユーザーです。そのため、deleteUser() の開始時にアクセス トークンを検証し、正しい新しいユーザーをロードすることを考えても、userDetailsImpl の実際の値には、testUpdateUser() の開始時に作成された間違ったユーザーが含まれています。

@Before
public void setup() {
    mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(filterChainProxy).build();
}

@Test
public void testUpdateUser() throws Exception {
    User savedUser = signUpUser();

    // @formatter:off
    mockMvc.perform(
            put("/users/" + savedUser.getId())
            .header(HeaderUtil.AUTHORIZATION, getAuthorizationWithAccessToken())
            .contentType(TestUtil.APPLICATION_JSON_UTF8)
            .content(TestUtil.convertObjectToJsonBytes(UserUpdateFormFactory.newInstance())))
            .andExpect(status().isOk())
            .andExpect(content().contentType(TestUtil.APPLICATION_JSON_UTF8))
            .andExpect(jsonPath("$.id", is(greaterThan(NumberUtils.INTEGER_ZERO))))
            .andExpect(jsonPath("$.name", is(equalTo(StringUtil.NEW + UserFactory.NAME))));
    // @formatter:on
}

@Test
public void testDeleteUser() throws Exception {
    User savedUser = signUpUser();
    String authorization = getAuthorizationWithAccessToken();

    // @formatter:off
    mockMvc.perform(
            delete("/users/" + savedUser.getId())
            .header(HeaderUtil.AUTHORIZATION, authorization)
            .contentType(TestUtil.APPLICATION_JSON_UTF8))
            .andDo(print())
            .andExpect(status().isNoContent());
    // @formatter:on
}

これは UserDetailService の実装です。アクセス トークンを検証する loadUserByUserName() に関しては、データベースから適切なユーザーをロードし、すべてのテスト メソッド (signUpUser()) の最初に作成されたばかりの新しいユーザーを返します。

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String email)
            throws UsernameNotFoundException {

        User requestedUser = new User();
        requestedUser.setEmail(email);

        User savedUser = userService.findByEmail(requestedUser);

        return new UserDetailsImpl(savedUser);
    }
}

失敗したセッションを無効にしようとしましたが、構成とテストコードで問題ないようです。spring-security-oauth の実用的な例はありますか?


更新しました

  1. mockMvc について私が理解している限りでは、すべての設定がクリアされ、 setUp() メソッドを使用して毎回ほとんど新しいモック サーバーが作成されます。したがって、アクセス トークン ストアは毎回クリアする必要がありますが、トークン ストアは認証されたトークンを維持します。

  2. テスト中に省略した「/oauth/token」で要求されたアクセス トークンを要求すると、次のように InMemoryTokenStore が呼び出されます。


テスト プロセス ログ

  1. testUpdateUser() -> POST: /oauth/token -> ストア トークン
    トークン: 50b10897-9e15-4859-aeb0-43d0802ba42c
    ユーザー: id=2

  2. testUpdateUser() -> PUT: /users/2 -> 読み取りトークン
    token: 50b10897-9e15-4859-aeb0-43d0802ba42c
    ユーザー: id=2

  3. testUpdateUserWithWrongUserId() -> GET: /oauth/token -> トークン
    トークンを保存: 50b10897-9e15-4859-aeb0-43d0802ba42c -> 既にトークン
    ユーザーに存在: id=2 -> id=4: ユーザーは新しいもので更新されました

  4. testUpdateUserWithWrongUserId() -> PUT: /users/0 -> 読み取りトークン
    token: 50b10897-9e15-4859-aeb0-43d0802ba42c
    ユーザー: id=2

  5. testDeleteUser() -> GET: /oauth/token -> トークンを保存するはずでしたが、トークンを保存しませんでした

  6. testDeleteUser() -> DELETE: /users/5 -> read token
    token: 50b10897-9e15-4859-aeb0-43d0802ba42c
    user: id=2 -> userSignUp() で作成された id=5 であるはずのユーザー


質問
mockMvc を使用してすべてのテスト メソッドで InMemoryTokenStore をクリアするにはどうすればよいですか?

4

1 に答える 1

0
    // ignore spring security session
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
于 2015-06-29T09:13:56.363 に答える