栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spirng框架之spring security(二)使用access()方法实现RBAC权限模型(另包涵简单动态菜单实现)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spirng框架之spring security(二)使用access()方法实现RBAC权限模型(另包涵简单动态菜单实现)

文章目录

目录

一、RBAC权限模型(表结构)

二、开发步骤

1. 生成数据表实体类

2. 定义JPA数据层访问接口(MyUserRepository)

3. 实现登录认证用户详情类(MyUserDetailsService)

4. 定义RBAC权限模型示例,Service接口

5. 定义RBAC权限模型示例,Service接口的实现类

6. 定义SecurityConfig类中access()方法自定义权限规则

7. 实现Controller类

8. 定义保存菜单数据的bean类

9. 实现菜单显示页menus.html

10. 登录认证、URL访问权限验证通过后的页面效果

11. 工程目录结构

总结


一、RBAC权限模型(表结构)

        RBAC权限模型:基于角色的访问控制。

        用户具有角色,角色拥有资源权限:表结构如下:

-- 用户表
create sequence SEQ_SYS_USER
minvalue 1
maxvalue 999999999999999
start with 1
increment by 1
nocache
order;

create table SYS_USER
(
  ID                    NUMBER(15) PRIMARY KEY, 
  USERNAME              VARCHAr2(50) not null,
  PASSWORD              VARCHAr2(200) not null,
  ADDTIME               DATE not null,
  ACCOUNTNonEXPIRED     NUMBER(1) not null, --账户是否过期
  ACCOUNTNonLOCKED      NUMBER(1) not null, --账户是否锁定
  CREDENTIALSNonEXPIRED NUMBER(1) not null, --密码是否过去
  ENABLED               NUMBER(1) not null  --账户是否可用
)


-- 资源权限表
create sequence SEQ_SYS_PERMISSION
minvalue 1
maxvalue 999999999999999
start with 1
increment by 1
nocache
order;

create table SYS_PERMISSION
(
  ID                    NUMBER(15) PRIMARY KEY,
  AVAILABLE             NUMBER(1) not null,
  NAME                  VARCHAr2(30) not null, --名称
  PARENT_ID             NUMBER(15) not null, --父ID
  PARENT_IDS            NUMBER(15) not null,
  PERMISSION            VARCHAr2(50) not null,
  RESOURCE_TYPE         VARCHAr2(50) not null, --类型:菜单、请求、按钮
  url                   VARCHAr2(100) not null --请求的URL
)


-- 角色表
create sequence SEQ_SYS_ROLE
minvalue 1
maxvalue 999999999999999
start with 1
increment by 1
nocache
order;

create table SYS_ROLE
(
  ID                    NUMBER(15) PRIMARY KEY,
  AVAILABLE             NUMBER(1) not null,
  DEscriptION            VARCHAr2(50) not null,
  ROLE                  VARCHAr2(50) not null
)


-- 角色、资源关联表,关联角色和资源权限
create table SYS_ROLE_PERMISSION
(
  ROLE_ID             NUMBER(15) not null,
  PERMISSION_ID       NUMBER(15) not null
)


-- 用户、角色关联表,关联用户和角色
create table SYS_USER_ROLE
(
  USER_ID             NUMBER(15) not null,
  ROLE_ID       NUMBER(15) not null
)

 

二、开发步骤

1. 生成数据表实体类

用户表SYS_USER实体类(重点注意@ManyToMany关联角色表)

package com.securitydemo.entity;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.*;
import java.util.*;


@Entity
@Table(name = "SYS_USER", schema = "PRODUCTION", catalog = "")
public class User implements UserDetails {
    private long id;
    private String password;
    private String username;
    private Date addtime;

    //用户关联到角色,RBAC权限模型
    private Set roles = new HashSet();

    //实现UserDetails接口重写的属性或方法
    //private Set authorities;//角色
    private Boolean accountNonExpired;//账户没有过期
    private Boolean accountNonLocked;//账户没有锁定
    private Boolean credentialsNonExpired;//密码没有过期
    private Boolean enabled;//账户可用


    @SequenceGenerator(name = "generator", sequenceName = "SEQ_A_TBL", allocationSize = 1)
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator")
    @Column(name = "ID", unique = true, nullable = false, scale = 0)
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    @Basic
    @Column(name = "PASSWORD")
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Basic
    @Column(name = "USERNAME")
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Basic
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "ADDTIME")
    public Date getAddtime() {
        return addtime;
    }

    public void setAddtime(Date addtime) {
        this.addtime = addtime;
    }

    @ManyToMany(targetEntity = SysRole.class, fetch = FetchType.EAGER)
    @JoinTable(name = "SYS_USER_ROLE", joinColumns = {@JoinColumn(name = "USER_ID")}, inverseJoinColumns = {@JoinColumn(name = "ROLE_ID")})
    public Set getRoles() {
        return roles;
    }

    public void setRoles(Set roles) {
        this.roles = roles;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        User that = (User) o;

        if (id != that.id) return false;
        if (password != null ? !password.equals(that.password) : that.password != null) return false;
        if (username != null ? !username.equals(that.username) : that.username != null) return false;
        if (addtime != null ? !addtime.equals(that.addtime) : that.addtime != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = (int) (id ^ (id >>> 32));
        result = 31 * result + (password != null ? password.hashCode() : 0);
        result = 31 * result + (username != null ? username.hashCode() : 0);
        result = 31 * result + (addtime != null ? addtime.hashCode() : 0);
        return result;
    }


    //实现UserDetails接口重写的属性或方法
    @Transient  //@Transient注释意思是不会被Spring Data JPA框架序列化到数据库,单纯的作为一个临时字段,接收完数据后就暂且用不上了
    @Override
    public Collection getAuthorities() {
        return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
    }

//    public void setAuthorities(Set authorities) {
//        this.authorities = authorities;
//    }

    @Column(name = "ACCOUNTNONEXPIRED")
    public Boolean getAccountNonExpired() {
        return accountNonExpired;
    }

    public void setAccountNonExpired(Boolean accountNonExpired) {
        this.accountNonExpired = accountNonExpired;
    }

    @Column(name = "ACCOUNTNONLOCKED")
    public Boolean getAccountNonLocked() {
        return accountNonLocked;
    }

    public void setAccountNonLocked(Boolean accountNonLocked) {
        this.accountNonLocked = accountNonLocked;
    }

    @Column(name = "CREDENTIALSNONEXPIRED")
    public Boolean getCredentialsNonExpired() {
        return credentialsNonExpired;
    }

    public void setCredentialsNonExpired(Boolean credentialsNonExpired) {
        this.credentialsNonExpired = credentialsNonExpired;
    }

    @Column(name = "ENABLED")
    public Boolean getEnabled() {
        return enabled;
    }

    public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
    }

    @Transient
    @Override
    public boolean isAccountNonExpired() {
        return accountNonExpired;
    }

    @Transient
    @Override
    public boolean isAccountNonLocked() {
        return accountNonLocked;
    }

    @Transient
    @Override
    public boolean isCredentialsNonExpired() {
        return credentialsNonExpired;
    }

    @Transient
    @Override
    public boolean isEnabled() {
        return enabled;
    }
}

角色表SYS_ROLE实体类(重点注意@ManyToMany关联到URL资源权限)

package com.securitydemo.entity;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;


@Entity
@Table(name = "SYS_ROLE", schema = "PRODUCTION", catalog = "")
public class SysRole {
    private long id;
    private Boolean availbale;
    private String description;
    private String role;

    //角色关联到URL资源权限,RBAC权限模型
    private Set Permissions = new HashSet();

    @SequenceGenerator(name = "generator", sequenceName = "SEQ_SYS_ROLE", allocationSize = 1)
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator")
    @Column(name = "ID", unique = true, nullable = false, scale = 0)
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    @Column(name = "AVAILABLE")
    public Boolean getAvailbale() {
        return availbale;
    }

    public void setAvailbale(Boolean availbale) {
        this.availbale = availbale;
    }

    @Column(name = "DEscriptION")
    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Column(name = "ROLE")
    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }

    @ManyToMany(targetEntity = SysPermission.class, fetch = FetchType.EAGER)
    @JoinTable(name = "SYS_ROLE_PERMISSION", joinColumns = {@JoinColumn(name = "ROLE_ID")}, inverseJoinColumns = {@JoinColumn(name = "PERMISSION_ID")})
    public Set getPermissions() {
        return Permissions;
    }

    public void setPermissions(Set permissions) {
        Permissions = permissions;
    }
}

资源权限表SYS_PERMISSION实体类

package com.securitydemo.entity;

import javax.persistence.*;


@Entity
@Table(name = "SYS_PERMISSION", schema = "PRODUCTION", catalog = "")
public class SysPermission {
    private long id;
    private Boolean availbale;
    private String name;
    private Long parentId;
    private Long parentIds;
    private String permission;
    private String resourceType;
    private String url;

    @SequenceGenerator(name = "generator", sequenceName = "SEQ_SYS_PERMISSION", allocationSize = 1)
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator")
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    @Column(name = "AVAILABLE")
    public Boolean getAvailbale() {
        return availbale;
    }

    public void setAvailbale(Boolean availbale) {
        this.availbale = availbale;
    }

    @Column(name = "NAME")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Column(name = "PARENT_ID")
    public Long getParentId() {
        return parentId;
    }

    public void setParentId(Long parentId) {
        this.parentId = parentId;
    }

    @Column(name = "PARENT_IDS")
    public Long getParentIds() {
        return parentIds;
    }

    public void setParentIds(Long parentIds) {
        this.parentIds = parentIds;
    }

    @Column(name = "PERMISSION")
    public String getPermission() {
        return permission;
    }

    public void setPermission(String permission) {
        this.permission = permission;
    }

    @Column(name = "RESOURCE_TYPE")
    public String getResourceType() {
        return resourceType;
    }

    public void setResourceType(String resourceType) {
        this.resourceType = resourceType;
    }

    @Column(name = "URL")
    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}

2. 定义JPA数据层访问接口(MyUserRepository)
package com.securitydemo.repository;

import com.securitydemo.entity.User;
import org.springframework.data.repository.CrudRepository;


public interface MyUserRepository extends CrudRepository {
    
    User findByUsername(String username);

}

3. 实现登录认证用户详情类(MyUserDetailsService)
package com.securitydemo.service.impl;

import com.securitydemo.entity.User;
import com.securitydemo.repository.MyUserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.List;


@Service
public class MyUserDetailsService implements UserDetailsService {

    
    private MyUserRepository myUserRepo;

    
    @Autowired
    public MyUserDetailsService(MyUserRepository userRepo){
        this.myUserRepo=userRepo;
    }

    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        System.out.println("username==="+username);
        //根据页面登录的用户名查询数据库用户信息进行身份认证start
        
        User user=myUserRepo.findByUsername(username);
        System.out.println("user-====="+user);
        //判断
        if(user!=null){
            System.out.println(user.getUsername()+"---====---"+user.getPassword()+"----"+user.getAddtime());
            return user;
        }
        throw new UsernameNotFoundException(username+"用户名不存在!");
        //根据页面登录的用户名查询数据库用户信息进行身份认证end

        
//        //手动设置了权限及角色,也可以通过数据库查询获取
//        List auths = AuthorityUtils.commaSeparatedStringToAuthorityList("addUser,findAll,ADMIN,USER");  //配置权限及角色
//        //根据页面登录的用户名查询数据库用户信息进行身份认证
//        return new User(atblUserLv.getUsername(),atblUserLv.getPassword(),auths);
    }
}

4. 定义RBAC权限模型示例,Service接口
package com.securitydemo.service;

import org.springframework.security.core.Authentication;
import javax.servlet.http.HttpServletRequest;


public interface RbacService {

    
    public boolean hasPermission(HttpServletRequest request, Authentication authentication);
}

5. 定义RBAC权限模型示例,Service接口的实现类
package com.securitydemo.service.impl;

import com.securitydemo.entity.SysPermission;
import com.securitydemo.entity.SysRole;
import com.securitydemo.entity.User;
import com.securitydemo.repository.MyUserRepository;
import com.securitydemo.service.RbacService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import javax.servlet.http.HttpServletRequest;
import java.util.HashSet;
import java.util.Set;


@Component("rbacService")
public class RbacServiceImpl implements RbacService {
    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Autowired
    private MyUserRepository myUserRepository;

    
    @Override
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        Object principal = authentication.getPrincipal();
        System.out.println("主体principal:"+principal);
        boolean hasPermission =false;
        if(principal!=null && principal instanceof UserDetails){
            //获取登录的用户名
//            String username = ((UserDetails) principal).getUsername();
//            System.out.println("主体principal-username:"+username);
//            //TODO:从数据库读取当前用户所拥有权限的url,放入set集合中
//            User user=myUserRepository.findByUsername(username);
            
            User user=((User) principal);
            Set urls = new HashSet<>();
            for(SysRole role : user.getRoles()){
                System.out.println("user.getRoles():"+role);
                for(SysPermission permission : role.getPermissions()){
                    System.out.println("permission.getUrl():"+permission.getUrl());
                    urls.add(permission.getUrl());
                }
            }

            //判断当前请求url,是否在拥有权限的url列表中(这里用antPathMatcher)
            for(String url:urls){
                System.out.println("授权url:"+url+"当前请求的URL:"+request.getRequestURI());
                if(antPathMatcher.match(url,request.getRequestURI())){
                    hasPermission = true;
                    break;
                }
            }
        }
        System.out.println("hasPermission:"+hasPermission);
        return hasPermission;
    }
}

6. 定义SecurityConfig类中access()方法自定义权限规则

    access():如果给定的SpEL表达式计算结果为true,就允许访问
    此例子中使用@Component("rbacService")自定义了一个组件bean类。实现了方法hasPermission判断请求的URL是否匹配上数据库中记录的URL,如果匹配上就返回true,否则返回false。
    SecurityConfig类中使用access()方法装配rbacService接口中的hasPermission()方法实现URL请求权限的判断。主要代码:                
.antMatchers("/","/logins","/test/hiRole").permitAll()
.anyRequest().access("@rbacService.hasPermission(request,authentication)")

package com.securitydemo.Config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.StandardPasswordEncoder;


@Configuration //表明是一个配置类bean
@EnableWebSecurity //此注解1: 加载了WebSecurityConfiguration配置类, 配置安全认证策略。2: 加载了AuthenticationConfiguration, 配置了认证信息。
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    
//    @Override
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        // 创建密码解析器
//        BCryptPasswordEncoder pe =new BCryptPasswordEncoder();
//        // 对密码进行加密
//        String password = pe.encode("a123456");
//        auth.inMemoryAuthentication()
//                .passwordEncoder(pe)  //默认没有,需要手动设置BCryptPasswordEncoder
//                .withUser("user01")
//                .password(password)
//                .roles("admin")
//                .and().withUser("user02").password(password).roles("user");
//
//    }

    
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        System.out.println("SecurityConfig run...configure(AuthenticationManagerBuilder auth)");
        
        auth.userDetailsService(userDetailsService);//.passwordEncoder(encoder());
    }

    
    @Bean
    public PasswordEncoder encoder(){
       return new BCryptPasswordEncoder();//进行转码 //NoOpPasswordEncoder.getInstance(); 不进行转码
    }

    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        System.out.println("SecurityConfig run...configure(HttpSecurity http)");

        //配置没有权限访问跳转自定义页面
       //http.exceptionHandling().accessDeniedPage("/error.html");
        //添加退出的映射地址
        http.logout().logoutUrl("/logout").logoutSuccessUrl("/").permitAll();

        http.authorizeRequests()
                //.antMatchers("/test/adduser","/test/findAllUser","/test/hello").hasRole("USER") //具备指定权限的用户且认证通过才能访问指定请求。hasRole方法中默认加有"ROLE_"前缀
                //.antMatchers("/","
@Controller //这个注解可返回显示视图页面。@RestController注解相当于@ResponseBody + @Controller合在一起的作用,方法返回字符串值
@RequestMapping("/test")
public class TestController {

    @Resource
    private UserService userService;
    @Autowired
    private MyUserRepository myUserRepository;

    @GetMapping("/hello")
    @ResponseBody //这个注解此方法表示返回字符串内容hello security
    public String hello(@AuthenticationPrincipal User user){
        System.out.println("了解登录用户是谁:"+user); //使用AuthenticationPrincipal注解,User是用户详情服务中的用户对象
        if(user!=null){
            System.out.println("了解登录用户是谁:"+user.getUsername()+"||"+user.getPassword()+"||"+user.getEnabled());
        }
        System.out.println("-----hello----");
        return "hello security";
    }

    @GetMapping("/adduser")
    public String addUser(@AuthenticationPrincipal User user){
        System.out.println("了解登录用户是谁:"+user); //使用AuthenticationPrincipal注解,User是用户详情服务中的用户对象
        if(user!=null){
            System.out.println("了解登录用户是谁:"+user.getUsername()+"||"+user.getPassword()+"||"+user.getEnabled());
        }
        System.out.println("-----添加用户----");
        AtblUserLv atblUserLv=new AtblUserLv();
        atblUserLv.setUsername("吕亮");
        atblUserLv.setPassword("12345");
        atblUserLv.setAddtime(new Date());
        userService.insertUser(atblUserLv);
        return "success";
    }

    @GetMapping("/findAllUser")
    public String findAllUsers(@AuthenticationPrincipal User user){
        System.out.println("了解登录用户是谁:"+user); //使用AuthenticationPrincipal注解,User是用户详情服务中的用户对象
        if(user!=null){
            System.out.println("了解登录用户是谁:"+user.getUsername()+"||"+user.getPassword()+"||"+user.getEnabled());
        }
        List list= userService.findAllUser();
        Iterator iter = list.iterator();
        while (iter.hasNext()){
            AtblUserLv atblUserLv=iter.next();
            System.out.println(atblUserLv.getId()+"||"+atblUserLv.getUsername()+"||"+atblUserLv.getPassword());
        }
        return "success";
    }

    @GetMapping("/hiRole")
    @ResponseBody //这个注解此方法表示返回字符串内容hello security
    public String helloRole(){
        System.out.println("-----helloRole----");
        return "hello Role!";
    }

    @GetMapping("/hiAnyRole")
    @ResponseBody //这个注解此方法表示返回字符串内容hello security
    public String helloAnyRole(){
        System.out.println("-----helloAnyRole----");
        return "hello AnyRole!";
    }

    @GetMapping("/findMenu")
    public String findMenus(@AuthenticationPrincipal User user, HttpServletRequest request, HttpServletResponse response){
        List listMenu=new ArrayList<>();
        System.out.println("findMenus开始执行:---------------------------");
        //User users=myUserRepository.findByUsername(user.getUsername());
        for(SysRole role : user.getRoles()){
            System.out.println("角色:"+role.getRole()+"======="+role.getPermissions());
            for(SysPermission permission : role.getPermissions()){
                if(permission.getResourceType().equals("menu")){
                    Menus menu=new Menus();
                    menu.setId(permission.getId());
                    menu.setName(permission.getName());
                    menu.setParentId(permission.getParentId());
                    menu.setParentIds(permission.getParentIds());
                    menu.setUrl(permission.getUrl());
                    listMenu.add(menu);
                }
            }
        }
        request.setAttribute("listMenus",listMenu);

        for(Menus menus:listMenu){
            if(menus.getParentId()==10000){ //10000为数据库中的值
                System.out.println("=="+menus.getName()+"["+menus.getUrl()+"]");
                for(Menus menusch:listMenu){
                    if(menus.getId()==menusch.getParentId()){
                        System.out.println("---------"+menusch.getName()+"["+menusch.getUrl()+"]");
                    }
                }
            }
        }
        return "menus";
    }
}

8. 定义保存菜单数据的bean类
package com.securitydemo.entity;


public class Menus {
    private long id;
    private String name;
    private Long parentId;
    private Long parentIds;
    private String url;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getParentId() {
        return parentId;
    }

    public void setParentId(Long parentId) {
        this.parentId = parentId;
    }

    public Long getParentIds() {
        return parentIds;
    }

    public void setParentIds(Long parentIds) {
        this.parentIds = parentIds;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}

9. 实现菜单显示页menus.html




    
    菜单列表


欢迎进入系统菜单

    
■ :
  ● :

没有查询到菜单!


退出

10. 登录认证、URL访问权限验证通过后的页面效果

11. 工程目录结构

 


总结

        本文重点内容是在开发步骤4、5、6步的RBAC权限模型的定义类RbacServiceImpl的实现上和配置类SecurityConfig中access("@rbacService.hasPermission(request,authentication)")方法的使用。另附带一个菜单页面的实现。

        本文是接另一遍文章“spirng框架之spring security(一)”的扩展,所以想要比较系统的了解可以先看“spirng框架之spring security(一)”,连接:(76条消息) spirng框架之spring security(一)_lv12345678的博客-CSDN博客https://blog.csdn.net/u011529483/article/details/123572622

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/786161.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号