来自 @PreAuthorize 的 hasRole 从哪里获取它在 Spring 中的值?

From where hasRole from @PreAuthorize take its values in Spring?

您好,我是 Spring 的新手,我想进一步了解安全模型。 在我们的项目中,我们控制哪个方法用

注释
@PreAuthorize("hasRole('REPORT_VIEW')")

所以我想知道这个 REPORT_VIEW 是从哪里来的,它是 ENUM 还是基于某些 xml 配置?我在文件中搜索但找不到 REPORT_VIEW 作为单词。

从这里开始: http://www.mkyong.com/spring-security/spring-security-access-control-example/

我看到有配置security-context.xml where

<user-service>
        <user name="mkyong" password="password" authorities="ROLE_USER" />
        <user name="eclipse" password="password" authorities="ROLE_ADMIN" />
</user-service>

在我的项目中

<sec:authentication-manager>
        <sec:authentication-provider user-service-ref="clientDetailsUserService" />
</sec:authentication-manager>

<bean id="clientDetailsUserService"
        class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
        <constructor-arg ref="clientDetails" />
</bean>

作为开发人员,我想从哪里创建一些控制器来了解应用程序的角色?

spring 安全的功能不是那么琐碎,但我试着解释一下:

Spring 安全认证是基于org.springframework.security.core.userdetails.UserDetails 的spring 用户抽象。 UserDetailsGrantedAuthority 可以是您的应用程序的权限、角色或任何其他 "SecurityItem"。 hasRole 检查当前用户是否有 GrantedAuthority 表达式中的名称(例如 'REPORT_VIEW')。

但是这些UserDetails是从哪里来的。这取决于您的应用程序。它们由 class 实现 org.springframework.security.core.userdetails.UserDetailsService 提供。这是您的应用程序的特定用户存储所在的地方。Spring 提供了几个已经实现的 UserDetailsService 但您也可以实现自己的(例如,如果您将用户凭据存储在自定义数据库中) .

在您链接的示例中,UserDetailsService 是基于 XML 创建和配置的(最简单的变体)。在您的应用程序中,UserDetails 是通过 OAuth2 提供的,它在您未提供的名为 clientDetails 的 bean 中定义。

我可以通过 XML 文件和一些 Java 代码向您解释。以下是我如何登录和分配角色。您还可以查询数据库中的角色。

安全-applicationContext.xml :

 <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider user-service-ref="LoginServiceImpl">
           <security:password-encoder  ref="encoder"/>
        </security:authentication-provider>
    </security:authentication-manager>


    <beans:bean id="daoAuthenticationProvider"
                class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
                <beans:property name="userDetailsService" ref="LoginServiceImpl"/>
               <beans:property name="passwordEncoder" ref="encoder"/>
    </beans:bean>

上面是我的DB认证码,它引用了LoginServiceImpl的bean,从那里我在DB中搜索用户。模型 class 已实现 UserDetails。

登录服务实现:

@Transactional
@Service("userDetailsService")
public class LoginServiceImpl implements UserDetailsService{

    @Autowired private PersonDAO personDAO;
    @Autowired private Assembler assembler;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException,DataAccessException {
        Person person = personDAO.findPersonByUsername(username.toLowerCase());
            if(person == null) { throw new UsernameNotFoundException("Wrong username or password");}
        return assembler.buildUserFromUserEntity(person);
    }

    public LoginServiceImpl() {
    }
}

当在数据库中找到用户时,我正在构建一个对象,spring-security 可以为会话和所有对象使用该对象。事情是这样的:

@Service("assembler")
public class Assembler {
    @Transactional(readOnly = true)
    User buildUserFromUserEntity(Person userEntity){
        String username = userEntity.getUsername().toLowerCase();
        String password = userEntity.getPassword();

        boolean enabled = userEntity.isEnabled();
        boolean accountNonExpired = userEntity.isAccountNonExpired();
        boolean credentialsNonExpired = userEntity.isCredentialsNonExpired();
        boolean accountNonLocked = userEntity.isAccountNonLocked();

        Collection<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));

        return new User(username,password,enabled,accountNonExpired,credentialsNonExpired,accountNonLocked,authorities);
        }
}

如您所见,我正在添加角色,但我也可以查询数据库或您找到的任何其他逻辑,然后将其移交,用户将拥有该角色。理想情况下,Person 模型 class 应该与 Role class 以及其中的用户角色具有一对多映射。 如果这不是您要找的,我会删除我的答案,请告诉我。