springboot + spring security 实现动态分配菜单权限和数据权限代码示例
时间: 2024-01-04 09:04:07 浏览: 111
springboot+security项目代码示例
以下是一个简单的示例代码,演示如何使用Spring Security实现动态分配菜单权限和数据权限。在本示例中,我们假设您已经创建了一个名为“menu”和一个名为“role”的数据库表。
首先,您需要定义菜单和角色的实体类:
```java
@Entity
@Table(name = "menu")
public class Menu {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String url;
private String icon;
private Long parentId;
// getter and setter
}
@Entity
@Table(name = "role")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String description;
private String menus; // 存储菜单ID的字符串,以逗号分隔
// getter and setter
}
```
然后,您需要为这些实体类创建相应的Repository接口:
```java
public interface MenuRepository extends JpaRepository<Menu, Long> {
}
public interface RoleRepository extends JpaRepository<Role, Long> {
}
```
接下来,您需要在Spring Security中配置角色和权限:
```java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("ADMIN", "USER")
.anyRequest().authenticated()
.and().formLogin().loginPage("/login").permitAll()
.and().logout().logoutUrl("/logout").permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
```
在上述配置中,我们定义了两个角色:“ADMIN”和“USER”,并将其与不同的资源进行关联。例如,只有拥有“ADMIN”角色的用户才能访问“/admin/**”路径。
接下来,您需要实现自定义的UserDetailsService类,以根据用户的角色动态生成菜单:
```java
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
@Autowired
private MenuRepository menuRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found with username: " + username);
}
List<GrantedAuthority> authorities = new ArrayList<>();
String[] roles = user.getRoles().split(",");
for (String roleName : roles) {
Role role = roleRepository.findByName(roleName);
if (role != null) {
authorities.add(new SimpleGrantedAuthority(role.getName()));
}
String[] menuIds = role.getMenus().split(",");
for (String menuId : menuIds) {
Menu menu = menuRepository.findById(Long.parseLong(menuId)).orElse(null);
if (menu != null) {
// 生成菜单
}
}
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
}
}
```
在上述代码中,我们首先获取用户所拥有的角色,然后根据角色获取对应的菜单。最后,我们将这些菜单生成为动态菜单,以供用户访问。
最后,您可以使用Spring Data JPA和Thymeleaf等技术实现动态生成菜单的功能。例如:
```html
<ul class="sidebar-menu">
<li th:each="menu : ${menus}" th:class="${menu.parentId == null ? 'treeview' : ''}">
<a th:href="@{${menu.url}}">
<i th:class="${menu.icon}"></i> <span th:text="${menu.name}"></span>
<i th:if="${menu.children.size() > 0}" class="fa fa-angle-left pull-right"></i>
</a>
<ul th:if="${menu.children.size() > 0}" class="treeview-menu">
<li th:each="child : ${menu.children}">
<a th:href="@{${child.url}}">
<i th:class="${child.icon}"></i> <span th:text="${child.name}"></span>
</a>
</li>
</ul>
</li>
</ul>
```
上述代码将根据用户所拥有的菜单动态生成侧边栏菜单。
阅读全文