我尝试使用模拟登录,@WithMockUser
但它不起作用。
@SpringBootTest
class RoleTest {
@Autowired
private UserService userService;
@Autowired
private RoleService roleService;
private User user;
@BeforeEach
void setUp() {
AuthentificationService.AuthentificationMock.loginAsAdminOnly();
user = new User("maier", "password", "Hansi", "Meier", "hanmai@maier.de", "+4953353535353", roleService.getByName(Role.ROLE_ADMIN).orElse(null));
assertNotNull(user.getRoles());
userService.save(user);
AuthentificationService.AuthentificationMock.logout();
}
@AfterEach
void tearDown() {
AuthentificationService.AuthentificationMock.loginAsAdminOnly();
userService.delete(user);
AuthentificationService.AuthentificationMock.logout();
}
@Test
@WithMockUser(Role.ADMIN)
void testRoleHierarchy() {
boolean succeeded = true;
//WHEN
try {
final Optional<User> byUsername = userService.getByUsernameResolved(user.getUsername());
} catch (Exception e) {
succeeded = false;
}
//THEN
assertTrue(succeeded, "ADMIN has no USER Privileges, check RoleHierarchy");
}
}
如果我运行测试身份验证AuthenticationCredentialsNotFoundException
,那么测试就会失败。
那就是访问受限的服务:
@Service
@Slf4j
@Transactional
@NoArgsConstructor
public class UserService implements JpaServiceContract<User>, UserDetailsService {
private UserRepository userRepository;
private AuthenticationManager authenticationManager;
private PasswordEncoder passwordEncoder;
@Autowired
public UserService(PasswordEncoder passwordEncoder, AuthenticationManager authenticationManager, UserRepository userRepository) {
this.userRepository = userRepository;
this.authenticationManager = authenticationManager;
this.passwordEncoder = passwordEncoder;
}
@Override
public UserDetails loadUserByUsername(@NotNull String username) {
final String callerName = SharedSecrets.getJavaLangAccess().getStackTraceElement(new Throwable(), 12).getClassName();
if (!callerName.equals("app.config.security.TokenAuthenticationFilter")) {
throw new MethodAccessException();
}
SecurityContextHolder.getContext().setAuthentication(new PreAuthenticatedAuthenticationToken(null, null, Collections.singletonList(new Role(Role.ADMIN))));
Optional<User> user = getByUsernameResolved(username);
SecurityContextHolder.clearContext();
final User user1 = user.orElse(null);
assert user1 != null;
return user1;
}
/**
* This Method is same as {@link #getByUsername(String)} but it resolves all Lazy loaded Properties,
* which could not be resolved outside of the current Transaction anymore
*
* @param username Of the {@link app.model.authentification.User} which should be found
* @return The {@link app.model.authentification.User} found as an {@link java.util.Optional}
*/
@RolesAllowed(value = Role.ROLE_USER)
public Optional<User> getByUsernameResolved(@NotNull String username) {
final Optional<User> userUnresolved = getByUsername(username);
userUnresolved.ifPresent(user -> Hibernate.initialize(user.getRoles()));
return userUnresolved;
}
@RolesAllowed(value = Role.ROLE_USER)
public Optional<User> getByUsername(@NotNull String username) {
if (!existsByUsername(username)) {
throw new RessourceNotFoundException("User not found");
}
return userRepository.findByUsername(username);
}
@Override
@RolesAllowed(Role.ROLE_USER)
public Optional<User> getById(@NotNull Long id) {
return userRepository.findById(id);
}
@Override
@RolesAllowed(Role.ROLE_USER)
public Optional<User> getByIdResolved(@NotNull Long id) {
final Optional<User> byId = getById(id);
if (byId.isPresent()) {
Hibernate.initialize(byId.get().getRoles());
return byId;
} else {
return Optional.empty();
}
}
@RolesAllowed(value = Role.ROLE_ADMIN)
@Override
public Set<User> getAll() {
return (Set<User>) userRepository.findAll();
}
@RolesAllowed(value = Role.ROLE_ADMIN)
@Override
public Set<User> getAllResolved() {
final Set<User> all = getAll();
Hibernate.initialize(all);
return all;
}
public User changePassword(@NotNull String oldPassword, @NotNull String newPassword) {
User user = getLoggedInUser();
user.setPassword(passwordEncoder.encode(newPassword));
return userRepository.save(user);
}
@Override
@RolesAllowed(value = Role.ROLE_USER)
public boolean existsById(@NotNull Long id) {
return userRepository.existsById(id);
}
@RolesAllowed(value = Role.ROLE_USER)
public boolean existsByUsername(@NotNull String username) {
return userRepository.existsByUsername(username);
}
@Override
@RolesAllowed(value = Role.ROLE_ADMIN)
public User save(@NotNull User user) throws RessourceAlreadyExistsException, InvalidParameterException {
if (UserValidator.isFullValid(user))
if (!userRepository.existsByUsername(user.getUsername())) {
user.setPassword(passwordEncoder.encode(user.getPassword()));
return userRepository.save(user);
} else {
throw new RessourceAlreadyExistsException(user.getUsername());
}
throw new InvalidParameterException(new String[]{"User"});
}
@Override
@RolesAllowed(Role.ROLE_USER)
public User update(@NotNull User user) throws InvalidParameterException {
if (UserValidator.isFullValid(user) && userRepository.existsByUsername(user.getUsername())) {
user.setPassword(passwordEncoder.encode(user.getPassword()));
return userRepository.save(user);
}
throw new InvalidParameterException(new String[]{"User"});
}
@Override
@RolesAllowed(value = Role.ROLE_ADMIN)
public void delete(@NotNull User user) throws IllegalArgumentException {
userRepository.delete(user);
}
@RolesAllowed(value = Role.ROLE_ADMIN)
public void delete(@NotNull String username) {
userRepository.deleteByUsername(username);
}
@RolesAllowed(value = Role.ROLE_USER)
private User getLoggedInUser() throws InvalidStateException {
Authentication currentUser = SecurityContextHolder.getContext().getAuthentication();
String username = currentUser.getName();
final Optional<User> userValue = getByUsername(username);
if (userValue.isPresent())
return userValue.get();
throw new InvalidStateException("User " + username + " not found");
}
}
如果您愿意,我可以提供更多配置信息,但目前我不知道这是否有必要。但如果你相信它,我会的。