Я реализовал Ouath2 в качестве защиты для моих контроллеров загрузки Spring. Перед вызовом любого из моих ресурсов oauth2 проверяет токен для пользователей в таблице user. Мой вопрос: как избежать ситуации, когда в запросе находится токен user1, а в теле запроса есть данные для модификации user2? Мне нужно поставить проверку, чтобы Пользователь1 со своим токеном мог изменять данные только для себя. Если user1 с его toekn имеет данные user2 в теле запроса, он должен выбросить 403.
Я думал, могу ли я получить имя пользователя из токена на уровне обслуживания, чтобы выполнить эту проверку? Любая помощь приветствуется
Вы можете сделать это, создав настраиваемую проверку.
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {OwnUserValidator.class})
public @interface OwnUser {
String message() default Messages.INVALID_WALLET;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
//
import org.springframework.beans.factory.annotation.Autowired;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class OwnUserValidator implements ConstraintValidator<OwnUser, String> {
@Override
public void initialize(OwnUser constraintAnnotation) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
String tokenName = THREAD_LOCAL_TOKEN.get();
if (tokenName.equalsIgnoreCase(value)){
return true;
}
return false;
}
}
затем используйте эту аннотацию @OwnUser перед пользовательским полем в теле запроса
public class Request implements Serializable{
private static final long serialVersionUID = 1L;
@OwnUser
private String user;
}
когда запрос вызывает метод doFilterInternal здесь, вы сохраняете токен в threadLocal:
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
public static ThreadLocal<String> THREAD_LOCAL_TOKEN = new ThreadLocal<>();
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
//get token from httpServlet request.
THREAD_LOCAL_TOKEN.set(nameFromtoken);
//ur neccessary code
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}
Вы используете Spring Security для аутентификации.
Вы можете получить сведения о пользователе из SecurityContext
Authentication authentication = SecurityContextHolder.getContext()
.getAuthentication();
UserDetails userDetail = authentication.getPrincipal();
userDetail.getUsername();
или в Rest Controller
@RequestMapping(value = "/username", method = RequestMethod.GET)
public String currentUserName(Principal principal) {
return principal.getName();
}
или же
@RequestMapping(value = "/username", method = RequestMethod.GET)
public String currentUserName(HttpServletRequest request) {
Principal principal = request.getUserPrincipal();
return principal.getName();
}
@RequestMapping (значение = "/ имя пользователя", метод = RequestMethod.GET) общедоступная строка currentUserName (основной участник) {return Principal.getName (); } Я получаю нулевой принцип