我是 Spring-Boot 的新手。我想创建一个 API,它将使用基于 JWT 令牌的身份验证进行基于角色的访问。但是,无法实现。
我没有使用 JPA 和 Hibernate 来获取和映射数据。相反,我使用的是 Ibatis。我尝试过使用@PreAuthorize和antMatchers & hasRole,但失败了。通过从 JWT 令牌获取用户 ID,我正在获取详细信息和角色并将它们设置为SecurityContextHolder.getContext().setAuthentication,但仍然无法正常工作。
安全配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilter(new JwtAuthorizationFilter(authenticationManager()))
.authorizeRequests()
.anyRequest().authenticated()
.antMatchers("api/management/reports").hasRole("Supervisor");
}
控制器
@RestController
@RequestMapping("api")
@CrossOrigin
public class MyController {
@PreAuthorize("hasRole('Supervisor')")
@GetMapping("username")
public String reports(){
SecurityContext securityContext = SecurityContextHolder.getContext();
return securityContext.getAuthentication().getName();
}
}
授权过滤器
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {
public JwtAuthorizationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String header = request.getHeader(JwtProperties.HEADER_STRING);
if (header == null || !header.startsWith(JwtProperties.TOKEN_PREFIX)) {
chain.doFilter(request, response);
return;
}
Authentication authentication = getUsernamePasswordAuthentication(request,header);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
private Authentication getUsernamePasswordAuthentication(HttpServletRequest request, String header) {
try {
String token = header.replace(JwtProperties.TOKEN_PREFIX,"");
String userName = JWT.require(HMAC512(JwtProperties.SECRET.getBytes()))
.build()
.verify(token)
.getSubject();
List<User> searchedUserList = getUserDetailsDAO().getUserDetails(userName);
if (null !=searchedUserList && searchedUserList.size()>0) {
User searchedUser = new User();
searchedUser = searchedUserList.get(0);
List<RoleAccess> roleAccessList = new ArrayList<RoleAccess>();
XrefUsrRole oXrefUsrRole = new XrefUsrRole();
oXrefUsrRole.setUserName(searchedUser.getUsername());
roleAccessList = getRoleAccessDAO().getAccessDetails(oXrefUsrRole);
List<GrantedAuthority> authorities = uildUserAuthority(roleAccessList);
org.springframework.security.core.userdetails.User newUser = buildUserForAuthentication(searchedUser, authorities);
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(newUser, null,authorities);
return auth;
}
return null;
}
return null;
} catch (IOException e) {
return null;
}
private org.springframework.security.core.userdetails.User buildUserForAuthentication(User searchedUser, List<GrantedAuthority> authorities) {
return new org.springframework.security.core.userdetails.User(searchedUser.getUsername(), searchedUser.getPassword(), true, true, true, true, authorities);
}
private List<GrantedAuthority> buildUserAuthority(List<RoleAccess> roleAccessList) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
// Build user's authorities
for (RoleAccess userRole : roleAccessList) {
setAuths.add(new SimpleGrantedAuthority("ROLE_"+userRole.getModifiedBy()));
}
List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths);
return Result;
}
在这种情况下,除了具有主管角色的用户之外,不应访问api/username。
您有ROLE_"+userRole.getModifiedBy())这意味着您正在授予角色ROLE_NAME并且在 PreAuthorize 中您有导致问题的主管。您可以将角色存储为 ROLE_SUPERVISOR 在数据库中,然后按如下方式使用它
// Build user's authorities
for (RoleAccess userRole : roleAccessList) {
setAuths.add(new SimpleGrantedAuthority("ROLE_"+userRole.getModifiedBy()));
}
用
@PreAuthorize("hasRole('ROLE_SUPERVISOR')")
.antMatchers("api/management/reports").hasRole("SUPERVISOR");
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句