1 需求01

  用户进行过认证登录后,某些接口是有权限限制的;如何实现只有相应权限的用户才可以调用相应接口

2 修改shiro配置类  ShiroConfiguration

package cn.xiangxu.apache_shiro;

import org.apache.shiro.mgt.SecurityManager;
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.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; /**
* Shiro配置类
*/
@Configuration
public class ShiroConfiguration { @Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager); shiroFilterFactoryBean.setLoginUrl("/login"); // 定义登录的url
shiroFilterFactoryBean.setSuccessUrl("/index"); // 定义登录成功后的url
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized"); // 没有权限时跳转的url LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); // 请求拦截配置
filterChainDefinitionMap.put("/index", "authc");
filterChainDefinitionMap.put("/login", "anon"); // 排除 login 的验证
filterChainDefinitionMap.put("/loginUser", "anon"); // 排除 loginUser 的验证
filterChainDefinitionMap.put("/admin", "roles[admin]");
filterChainDefinitionMap.put("/**", "user"); // 所有请求都必须进行登录过滤
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean;
} @Bean
public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm) {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(authRealm);
return defaultWebSecurityManager;
} /** 注入自定义密码比较器 */
@Bean
public CredentialMather credentialMather() {
return new CredentialMather();
} /** 注入自定义的授权、认证登录类 */
@Bean
public AuthRealm authRealm(@Qualifier("credentialMather") CredentialMather credentialMather) {
AuthRealm authRealm = new AuthRealm();
authRealm.setCredentialsMatcher(credentialMather);
return authRealm;
} /** Shiro与Spring整合配置 */
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
} }

  

  代码解释:只用用户角色为 admin 的用户才可以访问 /admin 接口

  原理请参见 RolesAuthorizationFilter 源码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// package org.apache.shiro.web.filter.authz; import java.io.IOException;
import java.util.Set;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.CollectionUtils; public class RolesAuthorizationFilter extends AuthorizationFilter {
public RolesAuthorizationFilter() {
} public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
Subject subject = this.getSubject(request, response);
String[] rolesArray = (String[])((String[])mappedValue);
if (rolesArray != null && rolesArray.length != 0) {
Set<String> roles = CollectionUtils.asSet(rolesArray);
return subject.hasAllRoles(roles);
} else {
return true;
}
}
}

RolesAuthorizationFilter

3 修改授权、认证登录配置类 AuthRealm

package cn.xiangxu.apache_shiro;

import cn.xiangxu.apache_shiro.model.Permission;
import cn.xiangxu.apache_shiro.model.Role;
import cn.xiangxu.apache_shiro.model.User;
import cn.xiangxu.apache_shiro.service.UserService;
import org.apache.commons.collections.CollectionUtils;
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 org.springframework.beans.factory.annotation.Autowired; import java.util.ArrayList;
import java.util.List;
import java.util.Set; /**
* 自定义授权、认证登录类
*/
public class AuthRealm extends AuthorizingRealm {
@Autowired
private UserService userService; // 授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
User user = (User)principalCollection.fromRealm(this.getClass().getName()).iterator().next(); // 从session中获取用户信息
List<String> permissionList = new ArrayList<>(); // 用于存放用户的权限列表
List<String> roleNameList = new ArrayList<>(); // 用于存放用户角色名称
Set<Role> roleSet = user.getRoleSet(); // 从用户信息中获取用户角色
if (CollectionUtils.isNotEmpty(roleSet)) {
for (Role role : roleSet) {
roleNameList.add(role.getRname());
Set<Permission> permissionSet = role.getPermissionSet();
if (CollectionUtils.isNotEmpty(permissionSet)) {
for (Permission permission : permissionSet) {
permissionList.add(permission.getPname());
}
}
}
} SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermissions(permissionList);
info.addRoles(roleNameList); return info;
} // 认证登录(使用用户名和密码进行登录认证)
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken)authenticationToken;
String username = usernamePasswordToken.getUsername(); // 取出用户名
User user = userService.findByUsername(username); // 根据用户名到数据库中去获取用户信息
return new SimpleAuthenticationInfo(user, user.getPassword(), this.getClass().getName());
}
}

  

  代码解释:将用户的角色名称提取出来并添加到 SimpleAuthorizationInfo 对象中

4 需求02

  一个用户已经认证登录成功,根据他所拥有的权限来判定他可以访问那些接口

 

5 重写shiro配置类  ShiroConfiguration

package cn.xiangxu.apache_shiro;

import org.apache.shiro.mgt.SecurityManager;
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.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; /**
* Shiro配置类
*/
@Configuration
public class ShiroConfiguration { @Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager); shiroFilterFactoryBean.setLoginUrl("/login"); // 定义登录的url
shiroFilterFactoryBean.setSuccessUrl("/index"); // 定义登录成功后的url
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized"); // 没有权限时跳转的url LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); // 请求拦截配置
filterChainDefinitionMap.put("/index", "authc");
filterChainDefinitionMap.put("/login", "anon"); // 排除 login 的验证
filterChainDefinitionMap.put("/loginUser", "anon"); // 排除 loginUser 的验证
filterChainDefinitionMap.put("/admin", "roles[admin]"); // 角色限定
filterChainDefinitionMap.put("/edit", "perms[edit]"); // 权限限定
filterChainDefinitionMap.put("/**", "user"); // 所有请求都必须进行登录过滤
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean;
} @Bean
public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm) {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(authRealm);
return defaultWebSecurityManager;
} /** 注入自定义密码比较器 */
@Bean
public CredentialMather credentialMather() {
return new CredentialMather();
} /** 注入自定义的授权、认证登录类 */
@Bean
public AuthRealm authRealm(@Qualifier("credentialMather") CredentialMather credentialMather) {
AuthRealm authRealm = new AuthRealm();
authRealm.setCredentialsMatcher(credentialMather);
return authRealm;
} /** Shiro与Spring整合配置 */
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
} }

  

  代码解释:只有拥有 edit 权限的用户才可以访问 /edit 接口

  原理请参见 PermissionsAuthorizationFilter 源码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// package org.apache.shiro.web.filter.authz; import java.io.IOException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.subject.Subject; public class PermissionsAuthorizationFilter extends AuthorizationFilter {
public PermissionsAuthorizationFilter() {
} public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
Subject subject = this.getSubject(request, response);
String[] perms = (String[])((String[])mappedValue);
boolean isPermitted = true;
if (perms != null && perms.length > 0) {
if (perms.length == 1) {
if (!subject.isPermitted(perms[0])) {
isPermitted = false;
}
} else if (!subject.isPermittedAll(perms)) {
isPermitted = false;
}
} return isPermitted;
}
}

PermissionsAuthorizationFilter

6 接口总汇

package cn.xiangxu.apache_shiro.controller;

import cn.xiangxu.apache_shiro.model.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpSession; //@RestController // 前后端分离时使用的注解
@Controller // 前后端不分离使用的注解
public class TestController { @RequestMapping(value = "/unauthorized")
public String unauthorized() {
return "unauthorized";
} @GetMapping("/login")
public String login() {
return "login";
} @GetMapping(value = "/index")
public String index() {
return "index";
} @GetMapping(value = "/logout")
public String logout() {
Subject subject = SecurityUtils.getSubject();
if (subject != null) {
subject.logout();
}
return "login";
} @GetMapping(value = "/admin")
@ResponseBody
public String admin() {
return "admin success";
} @GetMapping(value = "/edit")
@ResponseBody
public String edit() {
return "edit success";
} // 前后端不分离的写法
@PostMapping("/loginUser")
public String loginUser(
@RequestParam("username") String username,
@RequestParam("password") String password,
HttpSession session
) {
System.out.println("进入登录接口");
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
Subject subject = SecurityUtils.getSubject(); // 获取主体 // 认证登录逻辑(调用AuthRealm类的相关方法进行认证登录)
try {
subject.login(token); // 调用主体的login方法进行认证登录
User user = (User)subject.getPrincipal(); // 如果认证登录成功后就可以从主体中获取到数据库中主体对应的信息
session.setAttribute("user", user); // 将从数据库中获取到的主体信息放到session中,以便在权限验证的时候使用
return "index"; // 认证登录成功后就进入主页面
} catch (Exception e) {
e.printStackTrace();
return "login"; // 认证登录失败就进入登录页面
}
} // 前后端分离的写法
// @PostMapping("/loginUser")
// public String loginUser(
// @RequestBody User formUser,
// HttpSession session
// ) {
// System.out.println("进入登录接口" + formUser);
// UsernamePasswordToken token = new UsernamePasswordToken(formUser.getUsername(), formUser.getPassword());
// Subject subject = SecurityUtils.getSubject();
//
// try {
// System.out.println("进入捕获01");
// subject.login(token);
// User user = (User)subject.getPrincipal();
// System.out.println(user);
// session.setAttribute("user", user);
// System.out.println("进入捕获02");
// return "index"; // 热证登录成功就返回提示信息,在前端进行主页面跳转
// } catch (Exception e) {
// e.printStackTrace();
// return "login"; // 认证登录失败就返回提示信息,在前端进行登录页面跳转
// }
// }
}

7 开启Shiro缓存

  从 AuthorizingRealm 源码可以看出, AuthorizingRealm 可以依赖注入 CacheManager 来实现缓存

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// package org.apache.shiro.cache; public interface CacheManager {
<K, V> Cache<K, V> getCache(String var1) throws CacheException;
}

  技巧:CacheManager有两个实现类 -> 一个是MemoryConstrainedCacheManager, 一个是AbstractCacheManager

  只需要在shiro配置类中注入authRealm这个bean时添加一行代码就可以开启shiro缓存功能

  

package cn.xiangxu.apache_shiro;

import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.SecurityManager;
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.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; /**
* Shiro配置类
*/
@Configuration
public class ShiroConfiguration { @Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager); shiroFilterFactoryBean.setLoginUrl("/login"); // 定义登录的url
shiroFilterFactoryBean.setSuccessUrl("/index"); // 定义登录成功后的url
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized"); // 没有权限时跳转的url LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); // 请求拦截配置
filterChainDefinitionMap.put("/index", "authc");
filterChainDefinitionMap.put("/login", "anon"); // 排除 login 的验证
filterChainDefinitionMap.put("/loginUser", "anon"); // 排除 loginUser 的验证
filterChainDefinitionMap.put("/admin", "roles[admin]"); // 角色限定
filterChainDefinitionMap.put("/edit", "perms[edit]"); // 权限限定
filterChainDefinitionMap.put("/**", "user"); // 所有请求都必须进行登录过滤
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean;
} @Bean
public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm) {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(authRealm);
return defaultWebSecurityManager;
} /** 注入自定义密码比较器 */
@Bean
public CredentialMather credentialMather() {
return new CredentialMather();
} /** 注入自定义的授权、认证登录类 */
@Bean
public AuthRealm authRealm(@Qualifier("credentialMather") CredentialMather credentialMather) {
AuthRealm authRealm = new AuthRealm();
authRealm.setCacheManager(new MemoryConstrainedCacheManager()); // 开启内存缓存
authRealm.setCredentialsMatcher(credentialMather);
return authRealm;
} /** Shiro与Spring整合配置 */
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
} }

  

package com.mmall.demo2;

import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; import javax.sql.DataSource; @Configuration
public class DruidConfiguration { @Bean
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
//白名单:
servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
//IP黑名单 (存在共同时,deny优先于allow) : 如果满足deny的即提示:Sorry, you are not permitted to view this page.
servletRegistrationBean.addInitParameter("deny", "192.168.1.100");
//登录查看信息的账号密码.
servletRegistrationBean.addInitParameter("loginUsername", "druid");
servletRegistrationBean.addInitParameter("loginPassword", "12345678");
//是否能够重置数据.
servletRegistrationBean.addInitParameter("resetEnable", "false");
return servletRegistrationBean;
} @Bean
public FilterRegistrationBean statFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
//添加过滤规则.
filterRegistrationBean.addUrlPatterns("/*");
//添加不需要忽略的格式信息.
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
} @Bean
PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor() {
return new PersistenceExceptionTranslationPostProcessor();
} //配置数据库的基本链接信息
@Bean(name = "dataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource") //可以在application.properties中直接导入
public DataSource dataSource() {
return DataSourceBuilder.create().type(com.alibaba.druid.pool.DruidDataSource.class).build();
} @Bean
public SqlSessionFactoryBean sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
bean.setMapperLocations(resolver.getResources("classpath:/mappers/*.xml"));
return bean;
}
}

druid配置类

    

Shrio00 Shiro角色授权、Shiro权限授权、开启Shiro缓存的更多相关文章

  1. JAVAEE——BOS物流项目11:在realm中授权、shiro的方法注解权限控制、shiro的标签权限控制、总结shiro的权限控制方式、权限管理

    1 学习计划 1.在realm中进行授权 2.使用shiro的方法注解方式权限控制 n 在spring文件中配置开启shiro注解支持 n 在Action方法上使用注解 3.★使用shiro的标签进行 ...

  2. 简单两步快速实现shiro的配置和使用,包含登录验证、角色验证、权限验证以及shiro登录注销流程(基于spring的方式,使用maven构建)

    前言: shiro因为其简单.可靠.实现方便而成为现在最常用的安全框架,那么这篇文章除了会用简洁明了的方式讲一下基于spring的shiro详细配置和登录注销功能使用之外,也会根据惯例在文章最后总结一 ...

  3. 将 Shiro 作为应用的权限基础 二:shiro 认证

    认证就是验证用户身份的过程.在认证过程中,用户需要提交实体信息(Principals)和凭据信息(Credentials)以检验用户是否合法.最常见的“实体/凭证”组合便是“用户名/密码”组合. 一. ...

  4. 转:JAVAWEB开发之权限管理(二)——shiro入门详解以及使用方法、shiro认证与shiro授权

    原文地址:JAVAWEB开发之权限管理(二)——shiro入门详解以及使用方法.shiro认证与shiro授权 以下是部分内容,具体见原文. shiro介绍 什么是shiro shiro是Apache ...

  5. 将 Shiro 作为应用的权限基础 三:基于注解实现的授权认证过程

    授权即访问控制,它将判断用户在应用程序中对资源是否拥有相应的访问权限. 如,判断一个用户有查看页面的权限,编辑数据的权限,拥有某一按钮的权限等等. 一.用户权限模型 为实现一个较为灵活的用户权限数据模 ...

  6. 1、 Shiro框架:认证,授权(验权 2. Shiro框架实现权限控制方式:

    1. Shiro框架:认证,授权(验权) a) 认证逻辑:applicationCode—>通过工具类获取subject对象,调用login方法参数令牌信息->安全管理器------> ...

  7. 业务逻辑:五、完成认证用户的动态授权功能 六、完成Shiro整合Ehcache缓存权限数据

    一. 完成认证用户的动态授权功能 提示:根据当前认证用户查询数据库,获取其对应的权限,为其授权 操作步骤: 在realm的授权方法中通过使用principals对象获取到当前登录用户 创建一个授权信息 ...

  8. 第三章 授权——《跟我学Shiro》

    转发地址:https://www.iteye.com/blog/jinnianshilongnian-2020017 目录贴:跟我学Shiro目录贴 授权,也叫访问控制,即在应用中控制谁能访问哪些资源 ...

  9. Shiro学习(3)授权

    授权,也叫访问控制,即在应用中控制谁能访问哪些资源(如访问页面/编辑数据/页面操作等).在授权中需了解的几个关键对象:主体(Subject).资源(Resource).权限(Permission).角 ...

随机推荐

  1. flex TweenLite

    本贴已在 AS天地会转发,大家可以参考:http://bbs.actionscript3.cn/viewthread.php?tid=11090&pid=91142&page=1&am ...

  2. 【leetcode刷题笔记】Largest Rectangle in Histogram

    Given n non-negative integers representing the histogram's bar height where the width of each bar is ...

  3. css 行内元素 块元素 替换元素 非替换元素 以及这些元素的width height margin padding 特性

    一.各种元素的width height margin padding 特性(具体css元素的分来参看二) 1.块级元素 width. height. margin的四个方向. padding的四个方向 ...

  4. (vue.js)vue中引用了别的组件 ,如何使this指向Vue对象

    Vue中引用了别的组件 ,如何使this指向Vue对象 今天学习Vue组件传值, 通过创建Vue实例, 广播和监听实现传值, 但是传值之后无法直接将得到的值应用到Vue对象, 因为这相当于引用改了别的 ...

  5. LINQ 学习路程 -- 查询操作 OrderBy & OrderByDescending

    Sorting Operator Description OrderBy 通过给定的字段进行升序 降序 排序 OrderByDescending 通过给定字段进行降序排序,仅在方法查询中使用 Then ...

  6. 分享知识-快乐自己:Liunx 安装MySQL

    第一步: 1):下载mysql安装包:这里选择下载版本 5.6.33,通用版,linux下64位 http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql- ...

  7. Spring源码分析_01_ idea搭建spring源码阅读环境

    二.参考资料 1.Intellij Idea如何导入spring源码

  8. 【遍历二叉树】01二叉树的前序遍历【Binary Tree Preorder Traversal】

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 给定一个二叉树,返回他的前序遍历的 ...

  9. C语言小程序(四)、杨辉三角

    输入要显示的杨辉三角的行数,会打印出金字塔型的杨辉三角,不过行数太多的话,效果不太好,可以再调整一下格式控制. #include <stdio.h> #include <stdlib ...

  10. 搞事情 -- python之线程

    简介 操作系统线程理论 线程概念的引入背景 线程的特点 进程和线程的关系 使用线程的实际场景 用户级线程和内核级线程(了解) 线程和python 理论知识 线程的创建Threading.Thread类 ...