- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在使用 JWT token 和 Spring Boot 学习 Spring Security。我已经正确实现并且运行良好。但我对 JwtRequestFilter 的工作原理有一个疑问。我浏览了几个网站来了解 Spring Security 和 Spring Boot 并发现了同样的事情。那么让我来谈谈主要疑问。我在下面添加 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);
}
}
正如突出显示的那样,为了验证 token ,我们必须提供 spring UserDetails 对象,并且我们正在从 jwtUserDetailsService 获取 spring UserDetails 对象。因此,此过滤器将调用每个请求,然后将执行 token 验证,并且我们必须对每个请求调用 jwtUserDetailsService。我的疑问是在我的 jwtUserDetailsService 中,我添加了一些验证并添加了用户权限。因此,对于每个请求,都会在 jwtUserDetailsService 中重复以下步骤。
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;
}
}
因此,对于每个请求,这些查询都会执行。有更好的方法吗?因为一旦我在 Spring UserDetails 对象中添加用户权限,为什么我们需要对每个请求再次执行此操作。或者那些仅具有请求范围。我曾在 spring mvc 上工作过,一旦我们在 spring UserDetails 对象中添加权限,它就会一直存在,直到我点击注销,这意味着它将存在于 spring 安全上下文中,直到我们将其删除。 Spring Boot 中也会一样吗?如果我在 Spring UserDetails 对象中添加一次角色和权限详细信息,为什么我们需要再次添加它?
最佳答案
So every request this filter will call then token verification will perform and we have to call jwtUserDetailsService on every request.
这不可能是正确的,因为您有一个条件 if (SecurityContextHolder.getContext().getAuthentication() == null)
。
因此,第一次验证 token 时,您会查询用户详细信息服务,获取所有授权并将它们设置到安全上下文(您已经在执行此操作:SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
)。
此外,使用 JWT 身份验证,您通常甚至不需要访问任何用户详细信息服务,因为理想情况下所有授权都应包含在 token 本身中。因此,您唯一需要做的就是验证 token 的签名。
关于java - 带有 JWT token 的 Spring Security 在每个请求上加载 spring UserDetails 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58029611/
我正在尝试获取 session 数据,在 Service-GlobalServiceService 的 GetSessionData() 方法和我的 Component-HeaderComponent
Spring Security 有一个代表经过身份验证的用户的基类(org.springframework.security.core.userdetails.User): Models core u
我在应用程序中添加用户时遇到问题,放上代码。 //This is the SpringSecurityConfig class @Configuration public class SpringSe
我正在从用户创建 X-Auth-Token。但是,当我尝试从生成的 token 中检索用户时,它给了我一个异常 Warning: StandardWrapperValve[com.security
我有一个项目使用 spring boot,spring security 和 oauth2。当我使用 SecurityContextHolder.getContext().getAuthenticat
我已经看到,如果我想在 Spring Security 中激活并发控制,我必须添加: 到applicationContext并且: org.springframewor
我在 spring-boot 应用程序中使用 LDAP 身份验证(基于注释的配置)。我想自定义 UserDetails 对象。默认 UserDetails 实现是 LdapUserDetailsImp
如何通过将ManualUserDetails扩展org.springframework.security.core.userdetails.UserDetails添加到SecurityContextH
我需要保存一些有关用户的附加信息以排除过多的数据库请求。据我了解,我必须: 1)重写UserDetails接口(interface)。在此实现中保存我需要的所有附加信息。 2)重写UserDetail
我需要使用对象列表进行访问控制。获取该列表的查询非常复杂且冗长,因此当用户通过服务器进行身份验证时,我想将其缓存在用户对象中。我决定尝试通过 UserDetailService 和 WebSecuri
Spring Boot 应用程序具有自定义的 UserDetails。当应用程序所做的只是使用 User 类从数据库中验证现有用户时,一切正常。但是,当我尝试进行更改以便人们可以通过应用程序 GUI
我是 Spring Security 的新手。我已经实现了 UserDetails 来创建我自己的用户。我也有我的自定义 userDetailsService。现在一切正常,但我需要在不登录的情况
我正在使用 Grails 1.3.7。我有一个自定义 UserDetails在我的 customUserDetailsService 中创建的对象在认证过程中。我假设这个自定义 UserDetails
我有一个 Spring 项目,我正在将当前的身份验证转换为使用 SAML2。 就身份验证而言,我已经完成了所有工作,但是我很难让 SAML2 扩展将我的自定义 UserDetails 对象插入到 Sp
在我的 Web 应用程序中,我使用 Spring Security 和 UserDetailsService 实现进行身份验证。 现在我需要获取当前 session 的客户端 IP 地址并将其存储
我想向 userdetails 添加其他信息,例如用户的 IP 地址。有什么办法可以做到这一点?我试图创建一个新的 CustomSpringUser 类,但问题是我如何从 Authentication
我尝试使用 OAuth2 保护我的 Spring Boot 应用程序。在某些方面,一切正常。当我尝试从 oauth/token 获取访问 token 时端点第一次尝试我得到 token 没有问题。当我
我原以为我的授权实现已完成,但在尝试检索 UserDetails 对象时,我得到的只是用户名。 我正在使用具有以下细节的 oauth。 配置 AuthenticationManager: @Overr
我在我的网络项目中使用 SpringSecurity。我有保存在数据库中的实体用户。我需要使用用户 ID 在 BD 中执行请求,以从该 BD 中的其他表获取任何信息。在 Spring Security
我使用 LocalContainerEntityManagerFactoryBean 来设置 JPA EntityManagerFactory。在我使用 setPackagesToScan 扫描的扫描
我是一名优秀的程序员,十分优秀!