基于url的动态权限

方案一:扩展access()的SpEL表达式

.anyRequest().access("@authService.canAcess(request,authentication)")

方案二:自定义AccessDecisionManager

(1)自定义SecurityMetadataSource,实现从数据库加载ConfigAttribute

(2)自定义accessDecisionManager,进行权限校验

(3)使用withObjectPostProcessor,自定义SecurityMetadataSource和accessDecisionManager

方案三:自定义Filter

spring security本来就是由很多的Filter构成的,那么我们可以自定义Filter然后添加到fiterChain中

(1)需要提供认证数据规则数据源数据:通过实现接口FilterInvocationSecurityMetadataSource来进行实现。

(2)自定义accessDecisionManager:进行权限校验

(3)自定义一个拦截器然后把它添加到spring security的fiterChain

这里使用方案一。

一、创建实体类Permission

@Entity
public class Permission {
    @Id @GeneratedValue
    private long id; // 主键

    private  String name; // 权限名称

    private String description; // 权限名称

    /**
     * 注意:Permission表的ulr通配符为两颗星,比如/user下的所有url,应该写成/user/**
     */
    private String url; // 授权连接

    private Long pid; // 父节点

    // 角色 - 权限是多对多的关系
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "RolePermission",joinColumns = {@JoinColumn(name="permission_id")},inverseJoinColumns = {@JoinColumn(name="role_id")})
    private List<Role> roles;

    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 String getDescription() {
        return description;
    }

二、建立RoleRepository

public interface RoleRepository extends JpaRepository<Role,Long> {
}

三、创建service类

public interface PermissionService {
    Map<String, Collection<ConfigAttribute>> getPermissionMap ();
}

@Service
public class PermissionServiceImpl implements PermissionService {

    @Autowired
    private PermissionRepository permissionRepository;

    private Map<String, Collection<ConfigAttribute>> permissionMap = null;

    @PostConstruct
    /**
     * 从数据库中获取所有权限信息,然后进行遍历,存储到permissionMap集合中
     */
    public void initPermissions() {
        permissionMap = new HashMap<>();
        List<Permission> permissions = permissionRepository.findAll();
        for (Permission p : permissions) {
            Collection<ConfigAttribute> collection = new ArrayList<ConfigAttribute>();
            for (Role role : p.getRoles()) {
                ConfigAttribute configAttribute = new SecurityConfig("ROLE_"+role.getName());
                collection.add(configAttribute);
            }
            permissionMap.put(p.getUrl(),collection);
        }
        System.out.println(permissionMap);
    }

    @Override
    public Map<String,Collection<ConfigAttribute>> getPermissionMap (){
        if(permissionMap == null || permissionMap.size() == 0){
            initPermissions();
        }
        return permissionMap;
    }
}

四、初始化数据

@Service
public class DataInit {
    @Autowired
    private UserInfoRepository userInfoRepository;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private RoleRepository roleRepository;
    @Autowired
    private PermissionRepository permissionRepository;

    @PostConstruct
    public void dataInit(){
        // role
        List<Role> roles = new ArrayList<>();
        Role adminRole = new Role();
        adminRole.setName("admin");
        adminRole.setDescprtion("管理员");
        roleRepository.save(adminRole);
        roles.add(adminRole);

        Role userRole = new Role();
        userRole.setName("normal");
        userRole.setDescprtion("普通用户");
        roleRepository.save(userRole);
        roles.add(userRole);

        Permission userPermission = new Permission();
        userPermission.setName("普通用户的url");
        userPermission.setDescription("允许普通用户访问");
        userPermission.setUrl("/hello/helloUser");
        userPermission.setRoles(roles);
        permissionRepository.save(userPermission);

        Permission adminPermission = new Permission();
        adminPermission.setName("管理员的url");
        adminPermission.setDescription("允许管理员访问");
        adminPermission.setUrl("/hello/helloAdmin");
        roles = new ArrayList<>();
        roles.add(adminRole);
        adminPermission.setRoles(roles);
        permissionRepository.save(adminPermission);

        // admin
        UserInfo admin = new UserInfo();
        admin.setUsername("admin");
        admin.setPassword(passwordEncoder.encode("123"));
        admin.setRoles(roles);
        userInfoRepository.save(admin);

        // user
        roles = new ArrayList<>();
        roles.add(userRole);
        UserInfo user = new UserInfo();
        user.setUsername("user");
        user.setPassword(passwordEncoder.encode("123"));
        user.setRoles(roles);
        userInfoRepository.save(user);
    }
}

五、基于url动态获取权限并匹配

@Service
public class AuthService {
    @Autowired
    private PermissionService permissionService;
    public boolean canAcess(HttpServletRequest request, Authentication authentication) {
        boolean b = false;

        String url = request.getRequestURI();

        /**
         * 1、未登录的情况下,需要坐一个判断或者是拦截。
         */Object principal = authentication.getPrincipal();
        if(principal == null || "anonymousUser".equals(principal)) {
          return b;
        }

        /**
         * 2、匿名的角色ROLE_ANONYMOUS
         */
         if(authentication instanceof AnonymousAuthenticationToken) {
             // 匿名角色
             // check
             // return
         }

        /**
         * 3、通过requst对象url,获取到权限信息
         */
        Map<String, Collection<ConfigAttribute>> map = permissionService.getPermissionMap();
        Collection<ConfigAttribute>  configAttributes = null;
        for (Iterator<String> it = map.keySet().iterator();it.hasNext();) {
            String curUrl = it.next();
            AntPathRequestMatcher matcher = new AntPathRequestMatcher(curUrl);
            if (matcher.matches((request))) {
                configAttributes = map.get(curUrl);
                break;
            }
        }

        if(configAttributes == null || configAttributes.size() == 0) {
            return b;
        }

        /**
         * 4、将获取到的权限信息和当前的登陆账号的权限信息进行对比
         */
        for(Iterator<ConfigAttribute> it = configAttributes.iterator();it.hasNext();){
            ConfigAttribute cfa = it.next();
            String role = cfa.getAttribute();
            for(GrantedAuthority authority : authentication.getAuthorities()){
                if(role.equals(authority.getAuthority())){
                    b = true;
                    break;
                }
            }
        }

        return b;
    }
}

六、使用.anyRequest().access()

@Override
protected void configure (HttpSecurity http) throws Exception{
   http.formLogin().loginPage("/login")
   .and()
   .authorizeRequests()
           .antMatchers("/login").permitAll() //允许所有人可以访问登陆页面
    .antMatchers("/","/index").permitAll()
           .antMatchers("/test/**","/test1/**","/favicon.ico").permitAll()
           .antMatchers("/res/**/*.{js,html}").permitAll()

   .anyRequest().access("@authService.canAcess(request,authentication)")
   .and().sessionManagement().maximumSessions(1);
   //.anyRequest().authenticated();//所有的请求需要在登陆之后才能访问
}

遇到问题: 1、登陆成功后总是现实无权访问,这里先将首页设为所以可见。

.antMatchers("/","/index").permitAll()

2、登陆成功后总是访问/favicon.ico,导致权限无法匹配成功,解决办法是加一个/favicon.ico图片,再在使用的页面调用。还有更好的办法。 https://www.jianshu.com/p/b56e524ba2e8 https://blog.csdn.net/sdjadycsdn/article/details/82621234

转载于:https://my.oschina.net/u/2427561/blog/3101437

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RBAC(Role-Based Access Control)是一种基于角色的访问控制,它将权限授予角色,然后将角色授予用户。在Django中,可以使用django-guardian或django-rules等第三方库来实现RBAC权限管理,也可以自己编写代码实现。 下面是一个基于Django自己编写的简单RBAC权限管理系统的实现过程: 1. 定义权限模型 在Django中,可以通过定义模型来表示权限。例如,可以定义一个Permission模型,用来表示系统中的所有权限: ``` from django.db import models class Permission(models.Model): name = models.CharField(max_length=255, unique=True) codename = models.CharField(max_length=100, unique=True) ``` 其中name字段表示权限的名称,codename字段表示权限的代码名称。 2. 定义角色模型 同样地,可以定义一个Role模型,用来表示系统中的所有角色: ``` from django.db import models class Role(models.Model): name = models.CharField(max_length=255, unique=True) permissions = models.ManyToManyField('Permission') ``` 其中name字段表示角色的名称,permissions字段表示角色拥有的权限。 3. 定义用户模型 可以使用Django自带的User模型或者自己定义一个用户模型。在用户模型中,可以添加一个roles字段,用来表示用户所拥有的角色: ``` from django.contrib.auth.models import AbstractUser from django.db import models class User(AbstractUser): roles = models.ManyToManyField('Role') ``` 4. 编写权限检查装饰器 在Django中,可以使用装饰器来检查用户是否拥有某个权限。下面是一个简单的权限检查装饰器的实现: ``` from functools import wraps from django.http import HttpResponseForbidden def permission_required(perm): def decorator(view_func): @wraps(view_func) def _wrapped_view(request, *args, **kwargs): if not request.user.has_perm(perm): return HttpResponseForbidden() return view_func(request, *args, **kwargs) return _wrapped_view return decorator ``` 在上面的代码中,permission_required装饰器接受一个权限codename作为参数,返回一个装饰器函数。这个装饰器函数接受一个视图函数作为参数,返回一个新的视图函数。新的视图函数在执行前会检查用户是否拥有该权限,如果没有则返回403禁止访问状态码。 5. 在视图函数中使用权限检查装饰器 在需要进行权限检查的视图函数上加上permission_required装饰器即可: ``` @permission_required('app.view_model') def my_view(request): # do something ``` 在上面的代码中,my_view函数需要拥有view_model权限才能访问。 6. 编写角色管理视图 可以编写一个简单的角色管理视图,用来管理系统中的角色和权限: ``` from django.shortcuts import render from .models import Role, Permission def role_list(request): roles = Role.objects.all() return render(request, 'role_list.html', {'roles': roles}) def role_detail(request, role_id): role = Role.objects.get(id=role_id) permissions = Permission.objects.all() return render(request, 'role_detail.html', {'role': role, 'permissions': permissions}) ``` 在上面的代码中,role_list函数返回所有角色的列表,role_detail函数返回指定角色的详细信息和所有权限的列表。 7. 编写用户角色管理视图 可以编写一个简单的用户角色管理视图,用来管理用户和角色的关联关系: ``` from django.shortcuts import render from django.contrib.auth.models import User from .models import Role def user_list(request): users = User.objects.all() return render(request, 'user_list.html', {'users': users}) def user_detail(request, user_id): user = User.objects.get(id=user_id) roles = Role.objects.all() return render(request, 'user_detail.html', {'user': user, 'roles': roles}) ``` 在上面的代码中,user_list函数返回所有用户的列表,user_detail函数返回指定用户的详细信息和所有角色的列表。 8. 编写用户角色管理视图的表单处理函数 可以编写一个简单的表单处理函数,用来处理用户和角色的关联关系: ``` from django.shortcuts import redirect from django.contrib.auth.models import User from .models import Role def assign_role(request, user_id): if request.method == 'POST': user = User.objects.get(id=user_id) role_ids = request.POST.getlist('roles') roles = Role.objects.filter(id__in=role_ids) user.roles.set(roles) return redirect('user_detail', user_id=user_id) ``` 在上面的代码中,assign_role函数接受一个用户ID作为参数,从POST请求中获取选中的角色ID,将这些角色和用户关联起来,然后重定向到用户详细信息页面。 9. 编写角色管理视图的表单处理函数 可以编写一个简单的表单处理函数,用来处理角色和权限的关联关系: ``` from django.shortcuts import redirect from .models import Role, Permission def assign_permission(request, role_id): if request.method == 'POST': role = Role.objects.get(id=role_id) permission_ids = request.POST.getlist('permissions') permissions = Permission.objects.filter(id__in=permission_ids) role.permissions.set(permissions) return redirect('role_detail', role_id=role_id) ``` 在上面的代码中,assign_permission函数接受一个角色ID作为参数,从POST请求中获取选中的权限ID,将这些权限和角色关联起来,然后重定向到角色详细信息页面。 10. 编写模板 最后,可以编写一些简单的模板来渲染上述视图函数返回的数据。 例如,可以编写role_list.html模板来渲染角色列表: ``` <ul> {% for role in roles %} <li><a href="{% url 'role_detail' role.id %}">{{ role.name }}</a></li> {% endfor %} </ul> ``` 可以编写role_detail.html模板来渲染角色详细信息和权限列表: ``` <h1>{{ role.name }}</h1> <h2>Permissions</h2> <form method="post" action="{% url 'assign_permission' role.id %}"> {% csrf_token %} {% for permission in permissions %} <label> <input type="checkbox" name="permissions" value="{{ permission.id }}" {% if permission in role.permissions.all %}checked{% endif %}> {{ permission.name }} </label> {% endfor %} <button type="submit">Save</button> </form> ``` 可以编写user_list.html模板来渲染用户列表: ``` <ul> {% for user in users %} <li><a href="{% url 'user_detail' user.id %}">{{ user.username }}</a></li> {% endfor %} </ul> ``` 可以编写user_detail.html模板来渲染用户详细信息和角色列表: ``` <h1>{{ user.username }}</h1> <h2>Roles</h2> <form method="post" action="{% url 'assign_role' user.id %}"> {% csrf_token %} {% for role in roles %} <label> <input type="checkbox" name="roles" value="{{ role.id }}" {% if role in user.roles.all %}checked{% endif %}> {{ role.name }} </label> {% endfor %} <button type="submit">Save</button> </form> ``` 至此,一个简单的RBAC权限管理系统就完成了。当然,实际应用中可能需要更复杂的权限管理需求,可以根据具体情况进行扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值