Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JWT角色不起作用的Spring安全性_Java_Spring_Spring Security_Jwt - Fatal编程技术网

Java JWT角色不起作用的Spring安全性

Java JWT角色不起作用的Spring安全性,java,spring,spring-security,jwt,Java,Spring,Spring Security,Jwt,我正在使用SpringBoot和Java14 我正在尝试使基于角色的身份验证正常工作。我正在使用JWT。我可以让身份验证工作,也就是说,我获得JWT并成功地将该令牌用于所有未来的请求 但是,我无法使基于角色的权限正常工作,也就是说,如果安全配置尝试将端点与角色匹配,我总是会得到403 例如,如果我发送了以下请求,其中包含一个有效的jwt,并且用户具有正确的角色('approver admin'): 我得到以下答复: { "timestamp": "2020-

我正在使用SpringBoot和Java14

我正在尝试使基于角色的身份验证正常工作。我正在使用JWT。我可以让身份验证工作,也就是说,我获得JWT并成功地将该令牌用于所有未来的请求

但是,我无法使基于角色的权限正常工作,也就是说,如果安全配置尝试将端点与角色匹配,我总是会得到403

例如,如果我发送了以下请求,其中包含一个有效的jwt,并且用户具有正确的角色(
'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)。