当前位置: 首页 > 最新文章 > 正文

Spring安全的角色和权限源码与教程

企业应用程序包含多个部分,它不允许所有用户访问整个应用程序。具有ADMIN角色的用户将具有执行任何操作的完全权限。Spring安全性使使用角色和特权来构建这些类型的规则变得更加容易。在本文中,我们将了解如何使用Spring安全角色和特权功能来处理此类用例。这种多对多关系将为我们创建另一个数据库表UserEntity重点是与Group实体的关系。我们将填充以下2组:顾客行政2.向用户添加组分配给用户

admin

企业应用程序包含多个部分,它不允许所有用户访问整个应用程序。具有ADMIN角色的用户将具有执行任何操作的完全权限。Spring安全性使使用角色和特权来构建这些类型的规则变得更加容易。在本文中,我们将了解如何使用Spring安全角色和特权功能来处理此类用例。这种多对多关系将为我们创建另一个数据库表UserEntity重点是与Group实体的关系。我们将填充以下2组:顾客行政2.向用户添加组分配给用户的组上派生spring安全角色和权限。我们将对我们的DefaultUserService内容进行微小的更改。在注册过程中,我们会将组添加到用户个人资料中。

在本文中,我们将研究Spring安全角色和特权以及如何使用此功能来构建您的应用程序。

企业应用程序包含多个部分,它不允许所有用户访问整个应用程序。我们可能会提出一些要求,即我们希望根据用户角色和特权提供对应用程序的访问。让我们以管理电子商务商店的简单后端应用程序为例。

  1. 具有ADMIN角色的用户将具有执行任何操作的完全权限。
  2. 客户服务代理可以读取客户和订单信息,但看不到其他选项。
  3. 产品经理只能看到更新/创建产品的选项。

Spring安全性使使用角色和特权来构建这些类型的规则变得更加容易。我们可以在注册/创建过程中为用户分配角色和特权以及这些角色。在本文中,我们将了解如何使用Spring安全角色和特权功能来处理此类用例。为了确保我们有共同的理解,让我们看几个重要的术语。

  • Role角色:角色代表了系统的高级别角色(例如ADMIN,MANAGER等),每个角色都可以具有低级别的权限。
  • Privileges 权限:权限定义角色的低级权限(例如,ADMIN可以读取/写入/删除,但MANAGER只能读取/编辑)

可以从 GitHub Repository 下载完整的应用程序。

1.数据库设计

设计spring安全角色和权限的方法有多种,但是最常见和灵活的方法之一是围绕用户组构建角色和特权模块。作为任何应用程序的一部分,将用户分为几类,让我们以下面的示例为例,以便更好地理解:

  1. 前端用户应转到“CUSTOMER组”。
  2. 后端用户可以EMPLOYEE分组。
  3. 我们可以创建支持用户的另一个变体(例如ADMIN,MANAGER等等)

我们将使用相同的应用程序概念。应用程序的每个用户都将属于某个组,我们将使用这些组来驱动角色和权限。这是我们的应用程序的数据库设计。

Spring安全的角色和权限源码与教程

  1. 每个用户都属于某个组。
  2. 组将在注册/创建时分配给用户。
  3. principle_group 定义系统中所有可用的组(例如客户,管理员等)

UserGoup实体:

@Entity@Table(name = "principle_groups")public class Group{        //removed getter and setter to save space    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    private Long id;    @Column(unique = true, nullable = false)    private String code;    private String name;    @ManyToMany(mappedBy = "userGroups")    private Set<UserEntity> users;}

Group是一个简单的JPA实体,并包含了组名称和代码信息。有趣的部分是@ManyToMany与User实体的关系。这种多对多关系将为我们创建另一个数据库表

UserEntity重点是与Group实体的关系。

@Entity@Table(name = "user")public class UserEntity {    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    private Long id;    private String firstName;    private String lastName;    @Column(unique = true)    private String email;    private String password;    private String token;    private boolean accountVerified;    private int failedLoginAttempts;    private boolean loginDisabled;    @OneToMany(mappedBy = "user")    private Set<SecureToken> tokens;    @ManyToMany(cascade = {            CascadeType.PERSIST,            CascadeType.MERGE    })    @JoinTable(name = "user_groups",            joinColumns =@JoinColumn(name = "customer_id"),            inverseJoinColumns = @JoinColumn(name = "group_id"    ))    private Set<Group> userGroups= new HashSet<>();    public Set<Group> getUserGroups() {        return userGroups;    }    public void setUserGroups(Set<Group> userGroups) {        this.userGroups = userGroups;    }}

我们可以根据您的要求将数据填充到principal_groups表中。我们将填充以下2组:

  1. 顾客
  2. 行政
Spring安全的角色和权限源码与教程

2.向用户添加组

分配给用户的组上派生spring安全角色和权限。让我们更改注册过程,以将用户组分配给用户。我们将对我们的DefaultUserService内容进行微小的更改。在注册过程中,我们会将组添加到用户个人资料中。

@Service("userService")public class DefaultUserService implements UserService{    @Autowired    private UserRepository userRepository;    @Autowired    UserGroupRepository groupRepository;    @Override    public void register(UserData user) throws UserAlreadyExistException {        if(checkIfUserExist(user.getEmail())){            throw new UserAlreadyExistException("User already exists for this email");        }        UserEntity userEntity = new UserEntity();        BeanUtils.copyProperties(user, userEntity);        encodePassword(user, userEntity);        updateCustomerGroup(userEntity);        userRepository.save(userEntity);        sendRegistrationConfirmationEmail(userEntity);    }    private void updateCustomerGroup(UserEntity userEntity){        Group group= groupRepository.findByCode("customer");        userEntity.addUserGroups(group);    }}

您始终可以根据需要更改组分配逻辑。我们甚至可以在后端系统中构建逻辑以将组分配给用户。

3.自定义UserDetailsS​ervice实现

UserDetailsS​​ervice是Spring Security框架中的类,是用来检索用户的身份验证和授权信息的核心接口。该接口还负责提供用户GrantedAuthority列表,该列表用于为用户派生我们的spring安全角色和权限。让我们实现spring security的自定义UserDetailsS​​ervice,以返回GrantedAuthority基于用户组的列表。

@Service("userDetailsService")@Transactionalpublic class CustomUserDetailService implements UserDetailsService{    @Autowired    UserRepository userRepository;    @Override    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {        final UserEntity customer = userRepository.findByEmail(email);        if (customer == null) {            throw new UsernameNotFoundException(email);        }        boolean enabled = !customer.isAccountVerified(); // we can use this in case we want to activate account after customer verified the account        UserDetails user = User.withUsername(customer.getEmail())                .password(customer.getPassword())                .disabled(customer.isLoginDisabled())                .authorities(getAuthorities(customer)).build()                ;        return user;    }    private Collection<GrantedAuthority> getAuthorities(UserEntity user){        Set<Group> userGroups = user.getUserGroups();        Collection<GrantedAuthority> authorities = new ArrayList<>(userGroups.size());        for(Group userGroup : userGroups){            authorities.add(new SimpleGrantedAuthority(userGroup.getCode().toUpperCase()));        }        return authorities;    }}

这里有趣的事情是我们如何构建GrantedAuthority实体。我们使用一种简单的逻辑来构建GrantedAuthority与分配的用户组相同的列表。您可以更改/自定义逻辑以构建更复杂的GrantedAuthorities。

4. Spring Security Authority映射

通过UserDetailsS​​ervice实现子类,我们可以开始通过hasAnyAuthority()或hasAuthority()方法使用授权处理UI上的数据信息可见性。让我们看一下修改后的spring安全配置。

@Overrideprotected void configure(HttpSecurity http) throws Exception {    http.authorizeRequests()            .antMatchers("/login", "/register","/home")            .permitAll()            .antMatchers("/account/**").hasAnyAuthority("CUSTOMER", "ADMIN")            .and()            ...}

看着上面的配置中,我们告诉Spring security,只允许CUSTOMER和ADMIN权限用户访问 /account/**,注意用户授权是由UserDetailsService提供。您也可以使用相同的选项根据用户角色来显示/隐藏链接。这里将Spring安全性与Thymeleaf结合使用的示例代码。

<ul class="navbar-nav ml-auto">    <li class="dropdown user user-menu" sec:authorize="hasAnyAuthority('CUSTOMER', 'ADMIN')">        <a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">            <span class="hidden-xs" sec:authentication="name"></span>        </a>        <ul class="dropdown-menu">            <li class="user-header">                <img th:src="@{/dist/img/avatar5.png}" class="img-circle" alt="User Image">                <p>                    Spring Security Course                    <small>Java Development Journal</small>                </p>            </li>            <li class="user-footer">                <div class="pull-right">                    <a href="javascript: document.logoutForm.submit()" class="btn btn-default btn-flat">Sign out</a>                </div>            </li>        </ul>    </li>    <form name="logoutForm" th:action="@{/logout}" method="post" th:hidden="true">        <input hidden type="submit" value="Sign Out"/>    </form></ul>

原文链接:https://www.jdon.com/56457


上一篇: vue自定义指令使用(自定义el函数) 下一篇:iphone快速开始取消了怎么办(iphone关闭分析与改进)
返回顶部