Я изучаю пружинную безопасность с токеном JWT и загрузкой пружины.Я реализовал это правильно, и он работает нормально.Но у меня есть одно сомнение в том, как работает JwtRequestFilter.Я просмотрел несколько веб-сайтов, чтобы понять, как работает весенняя защита с помощью весенней загрузки, и нашел то же самое.Итак, позвольте мне перейти к основному сомнению.Я добавляю файл JwtRequestFilter ниже.
JwtRequestFilter.java
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private JwtUserDetailsService jwtUserDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
final String requestTokenHeader = request.getHeader("Authorization");
String username = null;
String jwtToken = null;
// JWT Token is in the form "Bearer token". Remove Bearer word and get
// only the Token
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
jwtToken = requestTokenHeader.substring(7);
try {
username = jwtTokenUtil.getUsernameFromToken(jwtToken);
} catch (IllegalArgumentException e) {
System.out.println("Unable to get JWT Token");
} catch (ExpiredJwtException e) {
System.out.println("JWT Token has expired");
}
} else {
logger.warn("JWT Token does not begin with Bearer String");
}
// Once we get the token validate it.
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
// This below line is calling on every request
UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);
// if token is valid configure Spring Security to manually set
// authentication
if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
// After setting the Authentication in the context, we specify
// that the current user is authenticated. So it passes the
// Spring Security Configurations successfully.
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
filterChain.doFilter(request, response);
}
}
Как выделено для проверки токена, мы должны предоставить объект Spring UserDetails и получить объект Spring UserDetails.от jwtUserDetailsService.Таким образом, каждый запрос, который вызовет этот фильтр, будет выполняться после проверки токена, и мы должны вызывать jwtUserDetailsService для каждого запроса.Мои сомнения находятся внутри моего jwtUserDetailsService. Я добавляю пару проверок и добавляю привилегии пользователя.Таким образом, для каждого запроса ниже шаги повторяются в jwtUserDetailsService.
- Получить пользователя, используя имя пользователя из БД.
- Получить роль пользователя
- Получить права пользователя из БД.
- Назначение привилегий для userDetails.
JwtUserDetailsService.java
@Service("jwtUserDetailsService")
@Transactional
public class JwtUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Autowired
private IUserService service;
@Autowired
private MessageSource messages;
@Autowired
private RoleRepository roleRepository;
@Override
public UserDetails loadUserByUsername(String email)
throws UsernameNotFoundException {
User user = userRepository.findByEmail(email);
if (user == null) {
return new org.springframework.security.core.userdetails.User(
" ", " ", true, true, true, true,
getAuthorities(Arrays.asList(
roleRepository.findByName("ROLE_USER"))));
}
return new org.springframework.security.core.userdetails.User(
user.getEmail(), user.getPassword(), user.isEnabled(), true, true,
true, getAuthorities(user.getRoles()));
}
private Collection<? extends GrantedAuthority> getAuthorities(
Collection<Role> roles) {
return getGrantedAuthorities(getPrivileges(roles));
}
private List<String> getPrivileges(Collection<Role> roles) {
List<String> privileges = new ArrayList<>();
List<Privilege> collection = new ArrayList<>();
for (Role role : roles) {
collection.addAll(role.getPrivileges());
}
for (Privilege item : collection) {
privileges.add(item.getName());
}
return privileges;
}
private List<GrantedAuthority> getGrantedAuthorities(List<String> privileges) {
List<GrantedAuthority> authorities = new ArrayList<>();
for (String privilege : privileges) {
authorities.add(new SimpleGrantedAuthority(privilege));
}
return authorities;
}
}
Таким образом, при каждом запросе эти запросы выполняются.Есть ли лучший способ сделать это?Потому что как только я весной добавляю пользовательские привилегии для объекта UserDetails, нам нужно делать это снова при каждом запросе.Или те, которые имеют объем запроса только.Я работал над Spring mvc, и как только мы добавим привилегии в весной объект UserDetails, он будет там, пока я не нажму выход из системы, значит, он будет там в контексте безопасности Spring, пока мы не удалим его.Будет ли это так же в весенней загрузке?Если я добавляю детали роли и привилегий один раз весной, объект UserDetails, зачем нам его снова добавлять?