首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Web 用戶權限管理系統設計與實現(RBAC 模型)

     編輯:Java 相關知識

前言

權限控制是企業級應用核心模塊。本文基於 RBAC(基於角色的訪問控制)模型,系統講解 Java Web 中用戶權限管理的數據庫設計、核心實體、權限檢查機制及主流框架整合方案。

一、RBAC 核心模型與表結構

1. 五張核心表

-- 用戶表
CREATE TABLE sys_user (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL UNIQUE,
    password VARCHAR(100) NOT NULL,
    salt VARCHAR(20),
    status TINYINT DEFAULT 1,
    create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- 角色表
CREATE TABLE sys_role (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    code VARCHAR(50) NOT NULL UNIQUE, -- 如 ROLE_ADMIN
    description VARCHAR(200)
);

-- 權限/資源表
CREATE TABLE sys_permission (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) NOT NULL,
    url VARCHAR(200),                 -- 菜單/按鈕/接口路徑
    perms VARCHAR(100),               -- 權限標識 user:add
    type TINYINT,                     -- 0目錄 1菜單 2按鈕
    parent_id BIGINT DEFAULT 0,
    sort INT DEFAULT 0
);

-- 用戶-角色關聯
CREATE TABLE sys_user_role (
    user_id BIGINT NOT NULL,
    role_id BIGINT NOT NULL,
    PRIMARY KEY (user_id, role_id)
);

-- 角色-權限關聯
CREATE TABLE sys_role_permission (
    role_id BIGINT NOT NULL,
    permission_id BIGINT NOT NULL,
    PRIMARY KEY (role_id, permission_id)
);

2. 實體類設計(簡化)

@Data
public class SysUser {
    private Long id;
    private String username;
    private String password;
    private Set<SysRole> roles; // 關聯角色
}

@Data
public class SysRole {
    private Long id;
    private String code; // ROLE_ADMIN
    private Set<SysPermission> permissions; // 關聯權限
}

@Data
public class SysPermission {
    private Long id;
    private String perms; // user:add
    private String url;   // /user/add
}

二、權限檢查核心流程

1. 認證階段

  • 用戶登錄 → 驗證密碼 → 生成 JWT/Session
  • 從數據庫加載用戶關聯的 roles 和 permissions 存入緩存

2. 授權階段(三種方式)

方式適用場景實現關鍵
URL 過濾器粗粒度接口保護FilterChainProxy + FilterInvocationSecurityMetadataSource
方法註解細粒度業務邏輯@PreAuthorize("hasAuthority('user:add')")
標籤/前端控制頁面元素顯隱Thymeleaf sec:authorize / Vue 指令 v-hasPermi

三、Spring Security 整合實戰

1. 核心配置類

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired UserDetailsService userDetailsService;
    @Autowired PasswordEncoder passwordEncoder;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/login", "/css/**", "/js/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin().loginPage("/login").permitAll()
            .and()
            .logout().permitAll();
    }
}

2. 自定義 UserDetailsService

@Service
public class CustomUserDetailsService implements UserDetailsService {
    @Autowired SysUserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) {
        SysUser user = userMapper.selectByUsername(username);
        if (user == null) throw new UsernameNotFoundException("用戶不存在");
        
        List<GrantedAuthority> authorities = user.getRoles().stream()
            .flatMap(role -> role.getPermissions().stream()
                .map(perm -> new SimpleGrantedAuthority(perm.getPerms())))
            .collect(Collectors.toList());
        
        return new User(user.getUsername(), user.getPassword(), authorities);
    }
}

3. 方法級權限控制

@Service
public class UserService {
    @PreAuthorize("hasAuthority('user:add')")
    public void addUser(UserDTO dto) { ... }

    @PreAuthorize("hasRole('ADMIN') or #id == authentication.principal.id")
    public void deleteUser(Long id) { ... }
}

四、Shiro 輕量級替代方案

若項目不需 Spring Security 複雜功能,Apache Shiro 更輕量:

[urls]
/login = anon
/user/** = authc, perms[user:view]
/admin/** = authc, roles[ADMIN]

// Realm 授權
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    info.addRoles(userRoles);
    info.addStringPermissions(userPerms);
    return info;
}

五、前端權限渲染最佳實踐

1. 路由守衛

// Vue Router
router.beforeEach((to, from, next) => {
    const perms = store.getters.permissions; // ['user:add', 'user:edit']
    if (to.meta.perms && !perms.includes(to.meta.perms)) {
        next({ path: '/403' });
    } else next();
});

2. 按鈕級指令

// directives/hasPermi.js
export default {
    mounted(el, binding) {
        const perms = store.getters.permissions;
        if (!perms.includes(binding.value)) el.parentNode?.removeChild(el);
    }
}
// 使用
<button v-hasPermi="'user:add'">新增</button>

六、進階優化策略

  1. 緩存權限:Redis 存儲 userId → Set<String> permissions,登錄時加載,變更時失效
  2. 動態路由:後端返回用戶菜單樹,前端 router.addRoutes 動態註冊
  3. 數據權限:MyBatis Plus DataPermissionHandler 自動拼接 dept_id IN (...)
  4. 審計日誌:AOP 切面記錄敏感操作 @OperLog("刪除用戶")

結語

Java Web 權限管理核心在於「用戶-角色-權限」三層映射與多層次攔截。推薦「Spring Security + JWT + Redis 緩存 + 前端指令」組合,兼顧安全性、性能與開發體驗。數據權限、審計日誌作為增強模塊按需接入。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved