当前位置: 主页 > JAVA语言

java控制按钮权限-基于角色的权限访问控制(Role-BasedAccessControl)的简介

发布时间:2023-06-15 22:06   浏览次数:次   作者:佚名

shiro框架整合 shiro简介 权限简介

对主体分配权限,主体只允许在权限范围内对资源进行操作,比如:对u01用户分配商品修改权限,u01用户只能对商品进行修改。

基于角色的权限访问控制

RBAC基于角色的访问控制(Role-Based Access Control)是以角色为中心进行访问控制,比如:主体的角色为总经理可以查询企业运营报表,查询员工工资信息等

基于资源的权限访问控制

RBAC基于资源的访问控制(Resource-Based Access Control)是以资源为中心进行访问控制,比如:主体必须具有查询工资权限才可以查询员工工资信息等

粗粒度和细粒度

对资源类型的管理称为粗颗粒度权限管理,即只控制到菜单、按钮、方法,粗粒度的例子比如:用户具有用户管理的权限,具有导出订单明细的权限。对资源实例的控制称为细颗粒度权限管理,即控制到数据级别的权限,比如:用户只允许修改本部门的员工信息,用户只允许导出自己创建的订单明细。

对于粗颗粒度的权限管理可以很容易做系统架构级别的功能,即系统功能操作使用统一的粗颗粒度的权限管理。

java控制按钮权限_java web菜单权限控制_java权限控制

对于细颗粒度的权限管理不建议做成系统架构级别的功能,因为对数据级别的控制是系统的业务需求,随着业务需求的变更业务功能变化的可能性很大,建议对数据级别的权限控制在业务层个性化开发,比如:用户只允许修改自己创建的商品信息可以在service接口添加校验实现,service接口需要传入当前操作人的标识,与商品信息创建人标识对比,不一致则不允许修改商品信息。

功能

Authentication:身份认证/登录,验证用户是不是拥有相应的身份;

Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;

Session Manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的;

Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;

Web Support:Web支持,可以非常容易的集成到Web环境;

Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;

java权限控制_java控制按钮权限_java web菜单权限控制

Concurrency:shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;

Testing:提供测试支持;

Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;

Remember Me:记住我,这个是非常常见的功能java控制按钮权限,即一次登录后java控制按钮权限,下次再来的话不用登录了。

构成

可以看到:应用代码直接交互的对象是Subject,也就是说Shiro的对外API核心就是Subject;其每个API的含义:

Subject:主体,代表了当前“用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等;即一个抽象概念;所有Subject都绑定到SecurityManager,与Subject的所有交互都会委托给SecurityManager;可以把Subject认为是一个门面;SecurityManager才是实际的执行者;

SecurityManager:安全管理器;即所有与安全有关的操作都会与SecurityManager交互;且它管理着所有Subject;可以看出它是Shiro的核心,它负责与后边介绍的其他组件进行交互,如果学习过SpringMVC,你可以把它看成DispatcherServlet前端控制器;

java控制按钮权限_java权限控制_java web菜单权限控制

Realm:域,Shiro从从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。

开始使用 依赖

	
        
            org.springframework.boot
            spring-boot-starter-thymeleaf
        
	
	
        
            com.github.theborakompanioni
            thymeleaf-extras-shiro
            2.0.0
        
        
         
        
            org.apache.shiro
            shiro-spring
            1.3.2
        

配置thymeleaf

	#在application.yml中配置
	
spring:
  thymeleaf:
  cache: false	#开发调试设置为false
   encoding: utf-8    servlet:
      content-type: text/html
    suffix: .html
    check-template-location: true
    prefix: classpath:/templates/

配置shiro

package com.example.shiro_btn.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
	/**
		注入这个是是为了在thymeleaf中使用shiro的自定义tag。
		*/
 @Bean(name = "shiroDialect")
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }
		/**
			
		*/
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean =new ShiroFilterFactoryBean();
        //设置securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //设置登录url
        shiroFilterFactoryBean.setLoginUrl("/login");
        //设置主页url
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //设置未授权的url
        shiroFilterFactoryBean.setUnauthorizedUrl("/error");
        Map filterChainDefinitionMap=new LinkedHashMap<>();
        //开放登录接口
        filterChainDefinitionMap.put("/login","anon");
        //设置主页 需管理员角色
        filterChainDefinitionMap.put("/index/**","roles[admin]");
        //开放静态页面
        filterChainDefinitionMap.put("/static/**","anon");
        //其余url全部拦截
        //必须放在最后
        filterChainDefinitionMap.put("/**","authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        System.out.println("shiro注入成功");
        return shiroFilterFactoryBean;
    }
		
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        /**
        	设置自定义的relam
        */
        securityManager.setRealm(loginRelam());
        return securityManager;
    }
    @Bean
    public LoginRelam loginRelam() {
        return new LoginRelam();
    }
    /**
    	以下是为了能够使用@RequiresPermission()等标签
    */
    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }
    @Bean
    public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
        return authorizationAttributeSourceAdvisor;
    }
}

自定义relam

java web菜单权限控制_java权限控制_java控制按钮权限

package com.example.shiro_btn.config;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import java.util.HashSet;
import java.util.Set;
public class LoginRelam extends AuthorizingRealm {
    /**
     * 角色授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String username = (String)SecurityUtils.getSubject().getPrincipal();
        Set roles =new HashSet();
        roles.add("admin");
        SimpleAuthorizationInfo info =new SimpleAuthorizationInfo();
        info.setRoles(roles);       //为当前登录用户添加角色
        Setpermissions=new HashSet<>();
        permissions.add("list");       //为当前用户设置权限
        info.setStringPermissions(permissions);
        return info;
    }
    /**
     * 身份认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token=(UsernamePasswordToken)authenticationToken;
        //@TODO 此处添加用户的校验操作
        SimpleAuthenticationInfo info =new SimpleAuthenticationInfo(token.getPrincipal(),"123",getName());
        return info;
    }
}

当运行一个Web应用程序时,Shiro将会创建一些有用的默认 Filter 实例,并自动地将它们置为可用,而这些默认的 Filter 实例是被 DefaultFilter 枚举类定义的,当然我们也可以自定义 Filter 实例,这些在以后的文章中会讲到

Filter 解释

anon 无参,开放权限,可以理解为匿名用户或游客

authc 无参,需要认证

logout 无参,注销,执行后会直接跳转到shiroFilterFactoryBean.setLoginUrl(); 设置的 url

authcBasic 无参,表示 httpBasic 认证

user 无参,表示必须存在用户,当登入操作时不做检查

java权限控制_java web菜单权限控制_java控制按钮权限

ssl 无参,表示安全的URL请求,协议为 https

perms[user] 参数可写多个,表示需要某个或某些权限才能通过,多个参数时写 perms[“user, admin”],当有多个参数时必须每个参数都通过才算通过

roles[admin] 参数可写多个,表示是某个或某些角色才能通过,多个参数时写 roles[“admin,user”],当有多个参数时必须每个参数都通过才算通过

rest[user] 根据请求的方法,相当于 perms[user:method],其中 method 为 post,get,delete 等

port[8081] 当请求的URL端口不是8081时,跳转到schemal://serverName:8081queryString 其中 schmal 是协议 http 或 https 等等,serverName 是你访问的 Host,8081 是 Port 端口,queryString 是你访问的 URL 里的 后面的参数

常用的主要就是 anon,authc,user,roles,perms 等

页面




    
    Title
    
    


hi,登录了

你好

list

登录

package com.example.shiro_btn.controller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@RequestMapping("/login")
@Controller
public class LoginController {
    @GetMapping
    public String index() {
        return "/login";
    }
    @PostMapping
    @ResponseBody
    public String login(String username,String password){
        UsernamePasswordToken token=new UsernamePasswordToken(username,password);
        SecurityUtils.getSubject().login(token);
        System.out.println("登陆成功");
        return "success";
    }
}