精华内容
下载资源
问答
  • api 接口 shiro 权限控制 springmvc

    千次阅读 2018-07-31 11:18:45
    采用前后端分离的方式,前端api接口访问,后端通过shiro权限控制。 设置跨域访问后,ajax携带cookie需要设置允许的access-orign。 可通过如下设置动态的。 // filter 中设置 if(request.getHeader("Origin&...

     

    采用前后端分离的方式,前端api接口访问,后端通过shiro权限控制。

    设置跨域访问后,ajax携带cookie需要设置允许的access-orign。

    可通过如下设置动态的。

    // filter 中设置
    if(request.getHeader("Origin").contains("mydomain.com")) {
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
    }
    
    <!-- springmv 配置设置 -->
    <mvc:cors>
            <mvc:mapping path="/**" allowed-origins="http://localhost:8081"/>
        </mvc:cors>

    现在想通过Token的方式去验证。

    用户登录后返回Token即SessionId

    前端:header中添加  Access-Token 值为SessionId

    后端:重写DefaultWebSessionManager中的getSessionId方法。

    先从Header取Token值,没有再按照默认取值:cookie->url->paramter。

    import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
    
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import java.io.Serializable;
    
    public class AccessTokenSessionManager extends DefaultWebSessionManager {
    
        public static final String ACCESS_TOKEN = "Access-Token";
    
        protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
            if(request instanceof HttpServletRequest){
                HttpServletRequest httpServletRequest = (HttpServletRequest) request;
                String sessionId = httpServletRequest.getHeader(ACCESS_TOKEN);
                if(sessionId!=null) {
                    return sessionId;
                }
            }
            return super.getSessionId(request,response);
        }
    
    
    }

    配置文件中指定SessionManager

    <bean id="sessionManager" class="com.tg.shop.context.shiro.session.AccessTokenSessionManager" ></bean>
    
    <!-- 安全管理器 -->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm" ref="sampleRealm"/>
            <property name="sessionManager" ref="sessionManager"/>
        </bean>

    还有一个问题:API返回的json值,shiro若(登录、角色、权限)验证未通过,会跳转URL而,ajax不能重定向。API接口期望返回JSON值。解决:可自定义ShiroFilter继承 AccessControlFilter,验证失败 直接response out自定义json即可。自定义的shiro需在配置文件中配置。

    <bean id="login" class="com.tg.shop.context.shiro.filter.LoginFilter"/>
    
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="filters">
                <util:map>
                    <entry key="login" value-ref="login"></entry>
                </util:map>
            </property>
    </bean>

     

    展开全文
  • 数据平行越权的漏洞最根本问题是,系统没有针对接口级别的权限控制。好多系统都是所有接口做个拦截器,只校验了是否登录,并没有把用户、角色权限和接口给关联起来。 以下讲下java web框架的解决思路。

    背景

    昨天被网安大队扫描安全漏铜,提到有个致命的安全漏洞:数据接口平行越权,要求半个月内整改完毕。数据平行越权用大白话说就是:我先用超级管理员登录后台系统,然后我记住了菜单A对应的URL。我在用普通管理员登录,但是没有菜单A的权限,但是我可以直接通过菜单A的URL进行访问。
    数据平行越权的漏洞最根本问题是,系统没有针对接口级别的权限控制。好多系统都是所有接口做个拦截器,只校验了是否登录,并没有把用户、角色权限和接口给关联起来。
    下图为网安大队安全漏洞报告截图:
    网安大队安全漏洞报告截图

    以下讲下java web框架的解决思路。

    解决方案

    JAVA后台变更:

    1. pom.xml 引入shiro对应的jar包:
    		<!-- 对shiro的支持 -->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.4.0</version>
            </dependency>
            <!-- shiro对redis的支持 -->
            <dependency>
                <groupId>org.crazycake</groupId>
                <artifactId>shiro-redis</artifactId>
                <version>2.4.2.1-RELEASE</version>
            </dependency>
    
    1. 需要权限控制的接口加入以下注解:
    @RequiresPermissions("student:getStudent")
        @RequestMapping(value = "getStudent",method= RequestMethod.POST)
        public ModelAndView getStudent()
        {
        	return new ModelAndView("/student");
        }
    
    1. application.yml 配置shiro 和redis 信息:
    spring:
      redis:
        shiro :
          host: 127.0.0.1
          port: 6379
          timeout : 0
          password:
    
    1. 统一异常处理类:MyExceptionHandler.java
    @Slf4j
    public class MyExceptionHandler implements HandlerExceptionResolver {
    
        public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception ex) {
        	ex.printStackTrace();
            ModelAndView mv = new ModelAndView();
            FastJsonJsonView view = new FastJsonJsonView();
            Map<String, Object> attributes = new HashMap<String, Object>();
            if (ex instanceof UnauthenticatedException) {
                attributes.put("sucess", "false");
                attributes.put("info", "token错误");
            } else if (ex instanceof UnauthorizedException) {
                attributes.put("sucess", "false");
                attributes.put("info", "用户无权限");
            } else {
                attributes.put("sucess", "false");
                attributes.put("info", ex.getMessage());
                log.error("发生未处理的异常={}",ex.getMessage(),ex);
            }
    
            view.setAttributesMap(attributes);
            mv.setView(view);
            return mv;
        }
    }
    
    
    1. 新建权限控制:MyShiroRealm.java
    public class MyShiroRealm extends AuthorizingRealm {
        @Resource
        private SysUserService sysUserService;
        @Autowired
        private SysRoleService sysRoleService;
    
        /**
         * 获取授权信息(把数据库中shiroID加入到shiro中管理,然后如果ctronler层方法加上@RequiresPermissions注解才会调用这个方法和数组进行比对)
    	 * 只有当需要检测用户权限的时候才会调用此方法
    	 */
    	@Override
    	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals)
    	{
    		//获取username
    		SysUser sysUser=(SysUser) SecurityUtils.getSubject().getSession().getAttribute("sysUserLogin");
    		List<SysPrivilege> sysPrivilegeList=sysPrivilegeList=sysRoleService.getSysPrivilegeByRoid(sysUser.getRoleId());
    		// 用户权限列表
    		Set<String> permsSet = new HashSet<>();
    		for (SysPrivilege perms : sysPrivilegeList)
    		{
    			if (StringUtils.isBlank(perms.getShiroID()))
    			{
    				continue;
    			}
    			permsSet.addAll(Arrays.asList(perms.getShiroID().trim().split(",")));
    		}
    		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    		info.addStringPermissions(permsSet);
    		return info;
    	}
    
        /**
         * 获取身份验证信息
         * 主要是用来进行身份认证的,也就是说验证用户输入的账号和密码是否正确。*/
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
                throws AuthenticationException {
    //        System.out.println("MyShiroRealm.doGetAuthenticationInfo()");
            //获取用户的输入的账号.
            String username = (String) token.getPrincipal();
    //        System.out.println(token.getCredentials());
            //通过username从数据库中查找 User对象,如果找到,没找到.
            //实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法
            SysUser userInfo = sysUserService.getByUserCode(username);
    //        System.out.println("----->>userInfo="+userInfo);
            if (userInfo == null) {
                return null;
            }
            if (Integer.parseInt(userInfo.getStates()) == 1) { //账户冻结
                throw new LockedAccountException();
            }
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                    token.getCredentials(), //用户名
                    userInfo.getPassword(),//salt=username+salt
                    getName()  //realm name
            );
            return authenticationInfo;
        }
    
    }
    
    1. 新建shiro 管理类:MySessionManager.java
    public class MySessionManager extends DefaultWebSessionManager {
    
        private static final String AUTHORIZATION = "Authorization";
    
        private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";
    
        public MySessionManager() {
            super();
        }
    
        @Override
        protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
            String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
            //适合于安卓,ios的或者前后端分离情况,直接在head头中传入sessionId的值(sessionId的键名为Authorization)
            if (!StringUtils.isEmpty(id)) {
                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE);
                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
                return id;
            } else {
                //适用于浏览器访问,否则按默认规则从cookie取sessionId
                return super.getSessionId(request, response);
            }
        }
    
    }
    
    1. 新建shiro 配置规则类:ShiroConfig.java
    @Configuration
    public class ShiroConfig {
    
        @Value("${spring.redis.shiro.host}")
        private String host;
        @Value("${spring.redis.shiro.port}")
        private int port;
        @Value("${spring.redis.shiro.timeout}")
        private int timeout;
        @Value("${spring.redis.shiro.password}")
        private String password;
    
        @Bean
        public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
            System.out.println("ShiroConfiguration.shirFilter()");
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);
    
            Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
            //注意过滤器配置顺序 不能颠倒
            //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了,登出后跳转配置的loginUrl
            filterChainDefinitionMap.put("/loginout", "logout");
            // 配置不会被拦截的链接 顺序判断
            filterChainDefinitionMap.put("/jqueryEasyui/**", "anon");
            filterChainDefinitionMap.put("/js/**", "anon");
            filterChainDefinitionMap.put("/theme/**", "anon");
            filterChainDefinitionMap.put("/druid/**", "anon");
            filterChainDefinitionMap.put("/ajaxLogin", "anon");
            filterChainDefinitionMap.put("/login", "anon");
            filterChainDefinitionMap.put("/demoOrder/**r", "anon");
            filterChainDefinitionMap.put("/**", "authc");
            //配置shiro默认登录界面地址,前后端分离中登录界面跳转应由前端路由控制,后台仅返回json数据
            shiroFilterFactoryBean.setLoginUrl("/index");
            // 登录成功后要跳转的链接
            shiroFilterFactoryBean.setSuccessUrl("/index");
            //未授权界面;
    //        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
            return shiroFilterFactoryBean;
        }
    
        /**
         * 凭证匹配器
         * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
         * )
         *
         * @return
         */
        @Bean
        public HashedCredentialsMatcher hashedCredentialsMatcher() {
            HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
            hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
            return hashedCredentialsMatcher;
        }
    
        @Bean
        public MyShiroRealm myShiroRealm() {
            MyShiroRealm myShiroRealm = new MyShiroRealm();
            myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
            return myShiroRealm;
        }
    
    
        @Bean
        public SecurityManager securityManager() {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            securityManager.setRealm(myShiroRealm());
            // 自定义session管理 使用redis
            securityManager.setSessionManager(sessionManager());
            // 自定义缓存实现 使用redis
            securityManager.setCacheManager(cacheManager());
            return securityManager;
        }
    
        //自定义sessionManager
        @Bean
        public SessionManager sessionManager() {
            MySessionManager mySessionManager = new MySessionManager();
            mySessionManager.setSessionDAO(redisSessionDAO());
            return mySessionManager;
        }
    
        /**
         * 配置shiro redisManager
         * <p>
         * 使用的是shiro-redis开源插件
         *
         * @return
         */
        public RedisManager redisManager() {
            RedisManager redisManager = new RedisManager();
            redisManager.setHost(host);
            redisManager.setPort(port);
            redisManager.setExpire(1800);// 配置缓存过期时间(登录是失效时间,0代表永不失效)
            redisManager.setTimeout(timeout);
            redisManager.setPassword(password);
            return redisManager;
        }
    
        /**
         * cacheManager 缓存 redis实现
         * <p>
         * 使用的是shiro-redis开源插件
         *
         * @return
         */
        @Bean
        public RedisCacheManager cacheManager() {
            RedisCacheManager redisCacheManager = new RedisCacheManager();
            redisCacheManager.setRedisManager(redisManager());
            return redisCacheManager;
        }
    
        /**
         * RedisSessionDAO shiro sessionDao层的实现 通过redis
         * <p>
         * 使用的是shiro-redis开源插件
         */
        @Bean
        public RedisSessionDAO redisSessionDAO() {
            RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
            redisSessionDAO.setRedisManager(redisManager());
            return redisSessionDAO;
        }
    
        /**
         * 开启shiro aop注解支持.
         * 使用代理方式;所以需要开启代码支持;
         *
         * @param securityManager
         * @return
         */
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
            AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
            authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
            return authorizationAttributeSourceAdvisor;
        }
    
        /**
         * 注册全局异常处理
         * @return
         */
        @Bean(name = "exceptionHandler")
        public HandlerExceptionResolver handlerExceptionResolver() {
            return new MyExceptionHandler();
        }
    }
    

    前端变更:

    1. 前端需要根据自己的框架,作统一的底层判断然后跳到统一的权限异常页面。
    2. 后台界面配置也需要支持对shiroid的管理。如下效果:
      在这里插入图片描述
      在这里插入图片描述

    源码地址:

    1. 获取完整源码地址: https://download.csdn.net/download/penggerhe/11670196
    2. 公众号关注,免费领取:
      在这里插入图片描述
    展开全文
  • 前后端分离之shiro实现权限控制的一些问题

    万次阅读 热门讨论 2018-06-02 17:33:02
    权限控制都是在后台实现,前端使用ajax调用后台接口。 但是ajax对接口返回的重定向是没发处理的,会出现异常(具体错误是哪个一时想不起来了);当shiro发现失效后的session时通常会将该请求重定向到loginUrl,...

    前言

    现在做项目,大多都是前后端分离;权限控制都是在后台实现,前端使用ajax调用后台接口。

    但是ajax对接口返回的重定向是没发处理的,会出现异常(具体错误是哪个一时想不起来了);当shiro发现失效后的session时通常会将该请求重定向到loginUrl,或者是用户访问的某个资源权限不足时(会重定向到unAuthorizedUrl),这时Ajax请求基本都是出错的。

    解决方案

    修改重定向302为正常返回200

    shiro默认实现了一些filter,使用不同的filter处理对应的权限拦截:

    /**
     * Enum representing all of the default Shiro Filter instances available to web applications.  Each filter instance is
     * typically accessible in configuration the {@link #name() name} of the enum constant.
     *
     * @since 1.0
     */
    public enum DefaultFilter {
    
        anon(AnonymousFilter.class),
        authc(FormAuthenticationFilter.class),
        authcBasic(BasicHttpAuthenticationFilter.class),
        logout(LogoutFilter.class),
        noSessionCreation(NoSessionCreationFilter.class),
        perms(PermissionsAuthorizationFilter.class),
        port(PortFilter.class),
        rest(HttpMethodPermissionFilter.class),
        roles(RolesAuthorizationFilter.class),
        ssl(SslFilter.class),
        user(UserFilter.class);
    

    当用户没有登录或session失效后,是使用FormAuthenticationFilter进行拦截处理的,我们可以重写里面的onAccessDenied方法,从而修改重定向。

    public class ShiroFormAuthenticationFilter extends FormAuthenticationFilter {
    
        @Override
        protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
            if (isLoginRequest(request, response)) {
                if (isLoginSubmission(request, response)) {
                    if (log.isTraceEnabled()) {
                        log.trace("Login submission detected.  Attempting to execute login.");
                    }
                    return executeLogin(request, response);
                } else {
                    if (log.isTraceEnabled()) {
                        log.trace("Login page view.");
                    }
                    //allow them to see the login page ;)
                    return true;
                }
            } else {
                HttpServletRequest req = (HttpServletRequest)request;
                HttpServletResponse resp = (HttpServletResponse) response;
                if(req.getMethod().equals(RequestMethod.OPTIONS.name())) {
                    resp.setStatus(HttpStatus.OK.value());
                    return true;
                }
    
                if (log.isTraceEnabled()) {
                    log.trace("Attempting to access a path which requires authentication.  Forwarding to the " +
                            "Authentication url [" + getLoginUrl() + "]");
                }
    			//前端Ajax请求时requestHeader里面带一些参数,用于判断是否是前端的请求
                String ajaxHeader = req.getHeader(ShiroConstant.USERID);
                if (ajaxHeader != null || req.getHeader("xx") != null) {
                    //前端Ajax请求,则不会重定向
                    resp.setHeader("Access-Control-Allow-Origin",  req.getHeader("Origin"));
                    resp.setHeader("Access-Control-Allow-Credentials", "true");
                    resp.setContentType("application/json; charset=utf-8");
                    resp.setCharacterEncoding("UTF-8");
                    PrintWriter out = resp.getWriter();
                    JSONObject result = new JSONObject();
                    result.put("message", "请重新登录!");
                    result.put("statusCode", -401);
                    out.println(result);
                    out.flush();
                    out.close();
                } else {
                    saveRequestAndRedirectToLogin(request, response);
                }
                return false;
            }
        }
    }
    

    同理,用户权限不足是使用AuthorizationFilter进行拦截处理的,我们依然可以重写里面的onAccessDenied方法,如下:

    public class ShiroRoleAuthorizationFilter extends AuthorizationFilter {
        
        @Override
        protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
            HttpServletRequest req = (HttpServletRequest)request;
            HttpServletResponse resp = (HttpServletResponse) response;
            if(req.getMethod().equals(RequestMethod.OPTIONS.name())) {
                resp.setStatus(HttpStatus.OK.value());
                return true;
            }
    		//前端Ajax请求时requestHeader里面带一些参数,用于判断是否是前端的请求
            String ajaxHeader = req.getHeader(ShiroConstant.USERID);
            if (ajaxHeader != null || req.getHeader("xx") != null) {
                //前端Ajax请求,则不会重定向
                resp.setHeader("Access-Control-Allow-Origin",  req.getHeader("Origin"));
                resp.setHeader("Access-Control-Allow-Credentials", "true");
                resp.setContentType("application/json; charset=utf-8");
                resp.setCharacterEncoding("UTF-8");
                PrintWriter out = resp.getWriter();
                JSONObject result = new JSONObject();
                result.put("message", "权限不足!");
                result.put("statusCode", -403);
                out.println(result);
                out.flush();
                out.close();
                return false;
            }
            return super.onAccessDenied(request, response);
        }
    }
    

    这样,前端Ajax请求被Shiro拦截后就不会出现返回302重定向的问题了。

    展开全文
  • springboot 前后端分离使用shiro进行权限控制并使用cors进行跨域 本来框架已经搭好了并且持续运行了一段时间前端已经能够拿到后台传过去的数据,cors配置 @Configuration //@EnableWebMvc public class WebConfig ...
  •      ...Shiro和SpringSecurity是都具备权限控制的两个框架,但是如果自己的小项目在权限控制方面要求比较简单,那么这两个框架就显得有些“重”,而且SpringSecurity配置起

           我们知道权限控制是不能交给前端去做的,因为一但后端的接口所暴露,是十分危险的一件事,所以前端发起的请求的安全性无从考证,最终的权限控制还是要交给后端去判断。
           ShiroSpringSecurity是都具备权限控制的两个框架,但是如果自己的小项目在权限控制方面要求比较简单,那么这两个框架就显得有些“重”,而且SpringSecurity配置起来还比较麻烦。
           本文所实现的权限控制是按等级划分的,即所有用户(游客、普通用户、管理员、超级管理员等)都有一个type字段来标识其身份:
    在这里插入图片描述
           例如-1指游客、0是普通用户、1是VIP、2是管理员、3是超级管理员等以此类推。这个字段即充当其“角色”,又充当其“权限(等级)”。其中低等级用户不能请求高等级的接口,高等级用户向下兼容,可以访问低等级的接口。
           详细代码如下,首先是:

    1. 权限枚举类

           我们首先要把权限枚举类定义出来:

    public enum AccessLevel {
    
        ALL(-1, "all"),
        LOGIN(0, "login"),
        VIP(1, "vip"),
        ADMIN(2, "admin"),
        SUPER(3, "super");
    
        int code;
        String msg;
    
        AccessLevel(int code, String msg) {
            this.code = code;
            this.msg = msg;
        }
    
        public int getCode() {
            return code;
        }
    
        public String getMsg() {
            return msg;
        }
    }
    

    2. 自定义权限控制注解

           其次是用在每个接口方法上的权限控制注解:

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @Documented     // 在生成javac时显示该注解的信息
    @Inherited
    public @interface Access {
        AccessLevel level() default AccessLevel.ALL; //默认为ALL
    }
    

    3. 自定义权限拦截器

           其次是自定义权限拦截器Interceptor:

    @Component
    public class AccessInterceptor extends HandlerInterceptorAdapter {
    
        private Logger logger = LoggerFactory.getLogger(AccessInterceptor.class);
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            if (!(handler instanceof HandlerMethod)) {
                return true;
            }
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            Access access = method.getAnnotation(Access.class);
            if (access == null) {
                // 如果注解为null, 说明不需要拦截, 直接放过
                return true;
            }
    
            // 如果是所有都能访问权限直接放行
            if (access.level() == AccessLevel.ALL) {
                return true;
            }
            if (access.level().getCode() >= AccessLevel.LOGIN.getCode()) {
            	//这里为自己写的获取登录用户的信息的方法,大家可以根据自己的方法修改
                User user = UserUtils.getLoginUser();
                if (user == null || user.getId() == null) {
                    response.setStatus(401);
                    logger.info("access " + method.getName() + " Not logged in");
                    return false;
                }
                if (user.getType() < access.level().getCode()) {
                    response.setStatus(403);
                    logger.info("access " + method.getName() + " No authority");
                    return false;
                }
            }
            return true;
        }
    

    4. 使用自定义权限拦截器

           我们需要使该拦截器生效:

    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new AccessInterceptor());
        }
    }
    

    5. 使用

           我们需要在方法上使用该注解:

    @GetMapping("/test")
    @Access(level = AccessLevel.VIP)
    public AjaxResponse test(){
    	AjaxResponse.setData("测试成功!");
    	return AjaxResponse.newSuccess();
    }
    

           这样我们就可以自己来实现最简单权限控制,大家还可以灵活去更改权限和拦截器。

    展开全文
  • 本文的github地址为:https://github.com/guanghuichen/shiro-jwt-redis 疫情期间在家闲的无聊,学习一下shiro和JWT的使用,平时工作中虽然一直用到但是始终没有从零到一搭建过,本文基于该github地址...
  • Shiro学习之权限控制

    2020-10-26 17:55:17
    权限控制这也是我们要用shiro框架的最主要的目的之一,对于有的接口,我们并不想让所有人都可以访问,有的加密接口需要指定权限才可以访问,我之前用Spring Security做过一次权限控制,这次学习Shiro框架也来实现...
  • shiro控制权限认证的原理

    千次阅读 2019-06-05 15:47:58
    现在在前端加上shiro的标签: shiro:hasPermission=“aaa”,访问该页面时,检测到shiro的标签,那么就会进入后端shiro权限校验: DelegatingSubject 实现 Subject接口,里面有个isPermitted(String permission)...
  • 新项目中用的Jeeplus框架,里面用的shiro权限控制,特别好用,但是如果单独写接口的话,总是会有登录验证,下面上思路实现一行代码让任意接口跳过登录限制。 正常代码生成机生成的代码不管它,这是每个模块都会自动...
  • 前后端分离项目springBoot +shiro权限控制+redis 本次使用shiro主要实现以下几个功能 ​ 1.用户没有登录无法访问任何为权限控制接口 ​ 2.用户登录后只能访问该用户所拥有的权限,实现了对后端接口颗粒级的权限控制...
  • 定义接口 /** * 允许jwt加密访问的接口,加载方法上 * @author gc */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface JWTAccess { } 添加测试接口 ...
  • 2.授权:授予权利访问某个页面或接口。 3.加密:shiro提供加密服务。保护数据的安全性,如密码加密存储到数据库,而不是明文存储。 4.会话管理:用户登录了一次就是会话,在一定时间内,用户的所有信息都保存在会话...
  • 网上很多介绍...本篇文章主要记录在SpringBoot2.x的基础上整合Shiro和Redis,实现权限控制与支持集群下的Session共享。 1、项目依赖 项目是基于Maven的,首先在pom.xml添加以下文件: <parent> ...
  • shiro中,接收到权限验证时,会生产唯一的sessionid,权限信息会保存在后端中(一般保存在redis中),并将sessionid写入前端,如果是链接请求,则需要返回sessionid,并将sessionid放在后期的访问头中。...
  • 1.项目简介 项目实现的思想和shiro框架类似,并在此基础之上扩展了数据过滤的功能 >有碰到和作者一样问题的人欢迎...项目中需要做权限控制,到接口级别 更加喜欢注解方式的控制,简单直观 集成shiro不成功,项...

空空如也

空空如也

1 2 3 4 5 ... 11
收藏数 214
精华内容 85
关键字:

shiro接口权限控制