Java JWT角色不起作用的Spring安全性
我正在使用SpringBoot和Java14 我正在尝试使基于角色的身份验证正常工作。我正在使用JWT。我可以让身份验证工作,也就是说,我获得JWT并成功地将该令牌用于所有未来的请求 但是,我无法使基于角色的权限正常工作,也就是说,如果安全配置尝试将端点与角色匹配,我总是会得到403 例如,如果我发送了以下请求,其中包含一个有效的jwt,并且用户具有正确的角色(Java JWT角色不起作用的Spring安全性,java,spring,spring-security,jwt,Java,Spring,Spring Security,Jwt,我正在使用SpringBoot和Java14 我正在尝试使基于角色的身份验证正常工作。我正在使用JWT。我可以让身份验证工作,也就是说,我获得JWT并成功地将该令牌用于所有未来的请求 但是,我无法使基于角色的权限正常工作,也就是说,如果安全配置尝试将端点与角色匹配,我总是会得到403 例如,如果我发送了以下请求,其中包含一个有效的jwt,并且用户具有正确的角色('approver admin'): 我得到以下答复: { "timestamp": "2020-
'approver admin'
):
我得到以下答复:
{
"timestamp": "2020-06-22T16:56:22.113+00:00",
"status": 403,
"error": "Forbidden",
"message": "Forbidden",
"path": "/approvals"
}
我的代码:
SecurityConfig.java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("datasource1")
private DataSource dataSource;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//auth.userDetailsService(approvalUserDetailsService);
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("SELECT username, password, (NOT disabled) as enabled FROM members "+
"WHERE username = ?")
.authoritiesByUsernameQuery("SELECT m.username, t.name as authority FROM members m " +
"JOIN administrator a ON a.member_id = m.member_id " +
"JOIN admin_type t ON t.admin_type_id = a.admin_type_id "+
"WHERE m.username = ?");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// set up the jwt auth
http.cors().disable();
http.csrf().disable().authorizeRequests().antMatchers("/authenticate").permitAll()//.anyRequest().authenticated()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.and().exceptionHandling()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // don't manage sessions, using jwt
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
// define the role mappings
http.authorizeRequests()
.antMatchers("/admin").hasRole("approver admin")
.antMatchers("/approvals").hasRole("approver admin")
.antMatchers("/hello").permitAll();
}
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private ApprovalUserDetailsService approvalUserDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
jwt = authorizationHeader.substring(7);
username = jwtTokenUtil.extractUserName(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.approvalUserDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validteToken(jwt, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
filterChain.doFilter(request, response);
}
}
@Service
public class ApprovalUserDetailsService implements UserDetailsService {
@Autowired
NamedParameterJdbcTemplate namedParameterJdbcTemplate;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
String sql = "SELECT username, password FROM members WHERE username = :userName";
// String sql = "SELECT m.username, m.password, t.name as authority FROM members m " +
// "JOIN administrator a ON a.member_id = m.member_id " +
// "JOIN admin_type t ON t.admin_type_id = a.admin_type_id " +
// "WHERE m.username = :userName";
SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("userName", userName);
User users = namedParameterJdbcTemplate.queryForObject(sql, namedParameters, new UserDetailsRowMapper());
return users;
// return new User("foo", "foo", new ArrayList<>());
}
class UserDetailsRowMapper implements RowMapper<User> {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
List<? extends GrantedAuthority> roles = new ArrayList<>();
//String authority = rs.getString("authority");
User user = new User(rs.getString("username"), rs.getString("password"), roles);
return user;
}
}
}
JwtRequestFilter.java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("datasource1")
private DataSource dataSource;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//auth.userDetailsService(approvalUserDetailsService);
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("SELECT username, password, (NOT disabled) as enabled FROM members "+
"WHERE username = ?")
.authoritiesByUsernameQuery("SELECT m.username, t.name as authority FROM members m " +
"JOIN administrator a ON a.member_id = m.member_id " +
"JOIN admin_type t ON t.admin_type_id = a.admin_type_id "+
"WHERE m.username = ?");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// set up the jwt auth
http.cors().disable();
http.csrf().disable().authorizeRequests().antMatchers("/authenticate").permitAll()//.anyRequest().authenticated()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.and().exceptionHandling()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // don't manage sessions, using jwt
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
// define the role mappings
http.authorizeRequests()
.antMatchers("/admin").hasRole("approver admin")
.antMatchers("/approvals").hasRole("approver admin")
.antMatchers("/hello").permitAll();
}
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private ApprovalUserDetailsService approvalUserDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
jwt = authorizationHeader.substring(7);
username = jwtTokenUtil.extractUserName(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.approvalUserDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validteToken(jwt, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
filterChain.doFilter(request, response);
}
}
@Service
public class ApprovalUserDetailsService implements UserDetailsService {
@Autowired
NamedParameterJdbcTemplate namedParameterJdbcTemplate;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
String sql = "SELECT username, password FROM members WHERE username = :userName";
// String sql = "SELECT m.username, m.password, t.name as authority FROM members m " +
// "JOIN administrator a ON a.member_id = m.member_id " +
// "JOIN admin_type t ON t.admin_type_id = a.admin_type_id " +
// "WHERE m.username = :userName";
SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("userName", userName);
User users = namedParameterJdbcTemplate.queryForObject(sql, namedParameters, new UserDetailsRowMapper());
return users;
// return new User("foo", "foo", new ArrayList<>());
}
class UserDetailsRowMapper implements RowMapper<User> {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
List<? extends GrantedAuthority> roles = new ArrayList<>();
//String authority = rs.getString("authority");
User user = new User(rs.getString("username"), rs.getString("password"), roles);
return user;
}
}
}
ApprovalUserDetailsService.java
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("datasource1")
private DataSource dataSource;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//auth.userDetailsService(approvalUserDetailsService);
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("SELECT username, password, (NOT disabled) as enabled FROM members "+
"WHERE username = ?")
.authoritiesByUsernameQuery("SELECT m.username, t.name as authority FROM members m " +
"JOIN administrator a ON a.member_id = m.member_id " +
"JOIN admin_type t ON t.admin_type_id = a.admin_type_id "+
"WHERE m.username = ?");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// set up the jwt auth
http.cors().disable();
http.csrf().disable().authorizeRequests().antMatchers("/authenticate").permitAll()//.anyRequest().authenticated()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.and().exceptionHandling()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // don't manage sessions, using jwt
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
// define the role mappings
http.authorizeRequests()
.antMatchers("/admin").hasRole("approver admin")
.antMatchers("/approvals").hasRole("approver admin")
.antMatchers("/hello").permitAll();
}
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private ApprovalUserDetailsService approvalUserDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
jwt = authorizationHeader.substring(7);
username = jwtTokenUtil.extractUserName(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.approvalUserDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validteToken(jwt, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
filterChain.doFilter(request, response);
}
}
@Service
public class ApprovalUserDetailsService implements UserDetailsService {
@Autowired
NamedParameterJdbcTemplate namedParameterJdbcTemplate;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
String sql = "SELECT username, password FROM members WHERE username = :userName";
// String sql = "SELECT m.username, m.password, t.name as authority FROM members m " +
// "JOIN administrator a ON a.member_id = m.member_id " +
// "JOIN admin_type t ON t.admin_type_id = a.admin_type_id " +
// "WHERE m.username = :userName";
SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("userName", userName);
User users = namedParameterJdbcTemplate.queryForObject(sql, namedParameters, new UserDetailsRowMapper());
return users;
// return new User("foo", "foo", new ArrayList<>());
}
class UserDetailsRowMapper implements RowMapper<User> {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
List<? extends GrantedAuthority> roles = new ArrayList<>();
//String authority = rs.getString("authority");
User user = new User(rs.getString("username"), rs.getString("password"), roles);
return user;
}
}
}
在ApprovalUserDetails服务中,ListHi Ken,感谢您的回答。我尝试了您的解决方案,即将其更改为
hasAuthority
,但仍然得到403
。请更新我的答案。对从userdetails服务返回的用户
需要填充“approver admin”谢谢,我会尝试一下org.springframework.security.core.userdetails.user
对象包含一个用户名
,密码
和一组权限
。您知道如何让RowMapper返回它吗?被注释掉的查询返回许多行,因此无法正常工作(结果大小不正确:预期为1,实际为19)。