SpringBoot Security 访问API始终报401

前言

用POSTMAN或者在页面前端登录访问后端API时,始终返回401.返回401有很多原因造成的,主要分为两个方面来看:

  1. 配置上的问题。确实没有权限。可以去检查一下数据库,看看相关的用户,权限有没有配上。
  2. 代码上的问题。配置上已经配置了权限,任然无法访问。

这里主要讲代码上的问题。

一、 UserDetails实现类里的getAuthorities重写方法,返回null.

public class UserDto extends DeepflowAbstractDto implements UserDetails {

 private String name;

 private String password;

 private Integer age;

 private String phoneNumber;

 private List<RoleDto> authorities;

 @Override
 public Collection<RoleDto> getAuthorities() {
   return null;
 }
 
 ...
}

getAuthorities这个方法是返回当前登录用户具有哪些角色,如果返回null的话,即使数据库里给用户配置了角色,框架也认为这个用户没有任何角色可以访问这个api,自然也就报401异常。这个问题一般是编写代码是粗心导致的,耗费了大量的时间而且不容易排查。所以写代码一定要细心呀。
代码改成下面应该就可以了:

public class UserDto extends DeepflowAbstractDto implements UserDetails {

  private String name;

  private String password;

  private Integer age;

  private String phoneNumber;

  private List<RoleDto> authorities;

  @Override
  public Collection<RoleDto> getAuthorities() {
    return authorities;
  }
  
  ...
}

二、 UserDetailsService实现类没有往登录用户里塞进角色信息

@Component
public class DeepflowUserDetailsService implements UserDetailsService {

  @Inject
  private UserService userService;

  @Inject
  private UserRoleService userRoleService;

  @Inject
  private RoleService roleService;

  @Override
  public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
    UserDto userDto = userService.findUserByName(userName);
    if (null != userDto) {
      List<Long> roleIds = userRoleService.findByUserId(userDto.getId())//
          .stream()//
          .map(UserRoleDto::getRoleId)//
          .collect(Collectors.toList());
      List<RoleDto> roleDtos = roleService.findByIds(roleIds);
      // userDto.setAuthorities(roleDtos);
    }

    return userDto;
  }

}

这里如果再给框架返回的用户信息里,没有用户的角色的话,在上一步return authorities;任然会返回一个null.所以这里把注释去掉应该就可以了。一般刚接触的可能会踩到这个坑。

三、访问@PreAuthorize修饰的方法报401

当访问某些被@PreAuthorize(“hasRole(‘ADMIN’)”)注解修饰的方法时,登录用户已经配置了ADMIN角色,可还是报401。一个可能的原因是,数据库中角色的名字要存为ROLE_ADMIN。
原因是源码org.springframework.security.access.vote.RoleVoter类中定义了一个前缀private String rolePrefix = “ROLE_”;,类中的supports方法会拿权限参数和rolePrefix进行匹配,查看是否是以ROLE_开头。

public class RoleVoter implements AccessDecisionVoter<Object> {
    // ~ Instance fields
    // ================================================================================================

    private String rolePrefix = "ROLE_";

    // ~ Methods
    // ========================================================================================================

    public String getRolePrefix() {
        return rolePrefix;
    }

    /**
     * Allows the default role prefix of <code>ROLE_</code> to be overridden. May be set
     * to an empty value, although this is usually not desirable.
     *
     * @param rolePrefix the new prefix
     */
    public void setRolePrefix(String rolePrefix) {
        this.rolePrefix = rolePrefix;
    }

    public boolean supports(ConfigAttribute attribute) {
        if ((attribute.getAttribute() != null)
                && attribute.getAttribute().startsWith(getRolePrefix())) {
            return true;
        }
        else {
            return false;
        }
    }
}

在supports方法中,会判断角色是否以ROLE_开头,如果不是的话,就会返回false.
解决办法:数据库中的角色名字以ROLE_为前缀存储

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot是一个开源的Java开发框架,用于构建独立的、可扩展的、基于Spring的应用程序。Spring Security是一个为Java应用程序提供身份认证和授权的框架,它提供了许多安全功能,如用户认证、角色管理和资源访问控制。OAuth2是一种用于授权的开放标准,它允许应用程序通过第三方身份验证服务器来获取访问令牌,以便访问受保护的资源。 要集成Spring Security OAuth2到Spring Boot 3.0的Web API中,需要以下步骤: 1. 添加依赖:在项目的pom.xml文件中添加Spring Security OAuth2的依赖。例如,可以添加以下依赖项: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> ``` 2. 配置Spring Security:创建一个配置类,扩展`WebSecurityConfigurerAdapter`,并重写`configure`方法来配置Spring Security。你可以定义用户认证方式和角色管理等配置。 3. 配置OAuth2:创建一个配置类,扩展`WebSecurityConfigurerAdapter`,并重写`configure`方法。在方法中配置OAuth2的相关信息,如认证服务器URL、客户端ID、客户端密码等。 4. 创建资源服务器:创建一个类,注解为`@RestController`,用于提供Web API接口。在方法上使用`@PreAuthorize`注解定义接口的访问权限。 通过以上步骤,你可以将Spring Boot 3.0的Web APISpring Security OAuth2集成起来。这样,你的应用程序将具有身份认证、角色管理和资源访问控制的功能,并可以使用OAuth2来授权访问受保护的资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值