一、@RestController和@Controller区别

  1. Controller, RestController的共同点

都是用来表示Spring某个类的是否可以接收HTTP请求

  1. Controller, RestController的不同点

@Controller标识一个Spring类是Spring MVC controller处理器

@RestController: @RestController是@Controller和@ResponseBody的结合体,两个标注合并起来的作用。

  1. 如果只是使用@RestController注解Controller,则Controller中的方法无法返回jsp页面,配置的视图解析器InternalResourceViewResolver不起作用,返回的内容就是Return 里的内容。

例如:本来应该到success.jsp页面的,则其显示success.

  1. 如果需要返回到指定页面,则需要用 @Controller配合视图解析器InternalResourceViewResolver才行。

  2. 如果需要返回JSON,XML或自定义mediaType内容到页面,则需要在对应的方法上加上@ResponseBody注解。

二、@GetMapping和@RequestMapping的区别

@GetMapping:是@RequestMapping(method = RequestMethod.GET)的缩写。

@GetMapping("/list")

@PostMapping:是@RequestMapping(method = RequestMethod.POST)的缩写

@RequestMapping(method = RequestMethod.GET  ,value = "/list")

三、MyBatis-Plus 通用IService使用介绍

四、Mapper接口动态代理调用过程

三、什么是shiro?Shiro能干嘛?

四、Shiro 实现原理与源码解析系统

五、权限控制(Shiro 注解)

六、在Security中实现Shiro的@RequiresPermissions注解

七、APACHE SHIRO框架@REQUIRESPERMISSIONS源码分析

八、Shiro

shiro简介
  • **Subject:**主体,可以看到主体可以是任何可以与应用交互的“用户”;

    // 登入
    subject.login(token);
    // 登出
    subject.logout();
    // 判断subject是否认证成功
    subject.isAuthenticated();
    // 判断subject是否具有admin和user两个角色权限,如没有则会报错
    subject.checkRoles("admin", "user");
    // 判断subject是否具有user:add权限
    subject.checkPermission("user:add");
    
  • **SecurityManager:**Shiro的心脏;所有具体的交互都通过SecurityManager进行控制;负责所有Subject、且负责进行认证和授权、及会话、缓存的管理。

    • Authenticator:认证器,判断用户是否正常登陆
    • Authorizer:授权器,判断用户是否有权限操作资源
  • **Realms:**可以有一个或者多个,作用 Authentication 是用来验证用户身份,Authorization 是授权访问控制,在调用subject.login(token)方法的时候触发

    1. 认证:从数据库查询出当前用户的密码与输入的密码进行比较,一致则通过认证
    2. 授权:从数据库查询出当前用户所拥有的角色和权限,用户–>角色(一对多),角色–>权限(多对多)
    3. 自定义Realms需要继承AuthorizingRealm ,重写doGetAuthenticationInfo和doGetAuthorizationInfo

**注意:**这里有一个坑,就是当我们想要使用RESTful风格返回给前台JSON数据的时候,这里有一个关于多对多无限循环的坑,比如当我们想要返回给前台一个用户信息时,由于一个用户拥有多个角色,一个角色又拥有多个权限,而权限跟角色也是多对多的关系,也就是造成了 查用户→查角色→查权限→查角色→查用户… 这样的无限循环,导致传输错误,所以我们根据这样的逻辑在每一个实体类返回JSON时使用了一个@JsonIgnoreProperties注解,来排除自己对自己无线引用的过程,也就是打断这样的无限循环。

shiro使用过程
  • 第一步,初始化SimpleAccountRealm将用户名和密码添加到一个Map<String, SimpleAccount> users中,将角色添加到 Map<String, SimpleRole> roles;permissions目前是空

    SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
    simpleAccountRealm.addAccount("wmyskxz", "123456","admin", "user");
    
  • 第二步,

// 1.构建SecurityManager环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(simpleAccountRealm);// 2.主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
// 设置SecurityManager环境
Subject subject = SecurityUtils.getSubject(); // 获取当前主体UsernamePasswordToken token = new UsernamePasswordToken("wmyskxz", "123456");
  • 从数据库中获取角色和权限

    // 调用登录接口会触发doGetAuthenticationInfo方法进行认证
    subject.login(token);
    //doGetAuthenticationInfo方法认证开始-----------
    // 1.从主体传过来的认证信息中,获得用户名
    String userName = (String) authenticationToken.getPrincipal();
    // 2.通过用户名到数据库中获取凭证
    String password = getPasswordByUserName(userName);
    SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo("wmyskxz", password, "myRealm");
    return authenticationInfo;
    //doGetAuthenticationInfo方法认证完成-------------// 调用doGetAuthorizationInfo进行授权============
    // 模拟数据库中获取角色
    Set<String> roles = new HashSet<>();
    roles.add("admin");
    roles.add("user");
    // 模拟数据库中获取权限
    Set<String> permissions = new HashSet<>();
    permissions.add("user:delete");
    permissions.add("user:add");simpleAuthorizationInfo.setStringPermissions(permissions);
    simpleAuthorizationInfo.setRoles(roles);
    // 放入SimpleAuthorizationInfo中完成授权=====================
    
  • 关于SimpleAuthenticationInfo

  • 判断是否具有权限

    // 判断subject是否具有admin和user两个角色权限,如没有则会报错
    subject.checkRoles("admin", "user");
    // 判断subject是否具有user:add权限
    subject.checkPermission("user:add");
    // subject.isAuthenticated()方法返回一个boolean值,用于判断用户是否认证成功
    subject.isAuthenticated() //true
    
  • 登出

    // 登出
    subject.logout();
    // 返回false
    subject.isAuthenticated();
    
Shiro 加密

加盐 + 多次加密

既然相同的密码 md5 一样,那么我们就让我们的原始密码再加一个随机数,然后再进行 md5 加密,这个随机数就是我们说的盐(salt),这样处理下来就能得到不同的 Md5 值,当然我们需要把这个随机数盐也保存进数据库中,以便我们进行验证。

另外我们可以通过多次加密的方法,即使黑客通过一定的技术手段拿到了我们的密码 md5 值,但它并不知道我们到底加密了多少次,所以这也使得破解工作变得艰难。

在 Shiro 框架中,对于这样的操作提供了简单的代码实现:

String password = "123456";String salt = new SecureRandomNumberGenerator().nextBytes().toString();int times = 2;  // 加密次数:2String alogrithmName = "md5";   // 加密算法String encodePassword = new SimpleHash(alogrithmName, password, salt, times).toString();System.out.printf("原始密码是 %s , 盐是: %s, 运算次数是: %d, 运算出来的密文是:%s ",password,salt,times,encodePassword);

输出:

原始密码是 123456 , 盐是: f5GQZsuWjnL9z585JjLrbQ==, 运算次数是: 2, 运算出来的密文是:55fee80f73537cefd6b3c9a920993c25
Shiro配置
@Configurationpublic class ShiroConfig {    @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>();        // 配置不会被拦截的链接 顺序判断        filterChainDefinitionMap.put("/static/**", "anon");        // 配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了        filterChainDefinitionMap.put("/logout", "logout");        // <!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;        // <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->        filterChainDefinitionMap.put("/**", "authc");        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面        shiroFilterFactoryBean.setLoginUrl("/login");        // 登录成功后要跳转的链接        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算法;        hashedCredentialsMatcher.setHashIterations(2); // 散列的次数,比如散列两次,相当于 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());        return securityManager;    }    /**     * 开启shiro aop注解支持.     * 使用代理方式;所以需要开启代码支持;     *     * @param securityManager     * @return     */    @Bean    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();        advisor.setSecurityManager(securityManager);        return advisor;    }    @Bean(name = "simpleMappingExceptionResolver")    public SimpleMappingExceptionResolver    createSimpleMappingExceptionResolver() {        SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();        Properties mappings = new Properties();        mappings.setProperty("DatabaseException", "databaseError"); // 数据库异常处理        mappings.setProperty("UnauthorizedException", "403");        r.setExceptionMappings(mappings);  // None by default        r.setDefaultErrorView("error");    // No default        r.setExceptionAttribute("ex");     // Default is "exception"        //r.setWarnLogCategory("example.MvcLogger");     // No default        return r;    }}

Apache Shiro 的核心通过 Filter 来实现,就好像 SpringMvc 通过 DispachServlet 来主控制一样。 既然是使用 Filter 一般也就能猜到,是通过URL规则来进行过滤和权限校验,所以我们需要定义一系列关于URL的规则和访问权限。

Filter Chain定义说明:

  • 1、一个URL可以配置多个Filter,使用逗号分隔
  • 2、当设置多个过滤器时,全部验证通过,才视为通过
  • 3、部分过滤器可指定参数,如perms,roles

Shiro内置的FilterChain,因表格显示问题,麻烦移步简书观看完整版…

  • anon:所有url都都可以匿名访问
  • authc: 需要认证才能进行访问
  • user:配置记住我或认证通过可以访问
Shiro自带的机制

// 通过username从数据库中查找 UserInfo 对象
// 实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该查询方法

Shiro的认证与授权流程解析
  1. Shiro常见3种授权判断方式:
Subject subject = SecurityUtils.getSubject();  if(subject.hasRole(“admin”)) {      //有权限  } else {      //无权限  }
@RequiresRoles("admin")  public void hello() {      //有权限  }
<shiro:hasRole name="admin">  <!— 有权限 —>  </shiro:hasRole>

jsp页面引入shiro标签

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags"%>
  1. 获取当前会话总人数
@Autowired
private SessionDAO sessionDAO;
//获取会话数量
int size = sessionDAO.getActiveSessions().size()
  1. 强制下线
//强制退出
Session session = sessionDAO.readSession(subject.getSession().getId());
sessionDAO.delete(session);
// logout,可作为强制退出
subject.logout();
Assert.isTrue(!subject.isAuthenticated());
shiro拦截器与url匹配规则
拦截器和过滤器的区别

人人开发--知识点记录相关推荐

  1. Android开发中的一些小知识点记录(101-120)

    编写不易,如有转载,请声明出处:http://blog.csdn.net/zxc514257857/article/details/118554522 Android开发中的一些小知识点记录(1-20 ...

  2. javaweb基础知识点记录2

    javaweb基础知识点记录 1.在service方法中,首先获得请求的方法名,然后根据方法名调用对应的doXXXX方法,比如说请求参数为GET,那么就会去调用doGet方法,请求参数为POST,那么 ...

  3. C++后端开发知识点总结

    C++后端开发知识点总结 C++后端开发知识点总结 C++ 1. 全局变量的作用域与初始化 2. 字节对齐的计算方法 3. 类的静态成员 4. 纯虚函数的用法 5. 构造函数和析构函数的执行顺序 6. ...

  4. 测试开发知识点整理(二)

    软件测试基础 软件测试的概念 63.软件测试的重要性 64.软件测试的对象有哪些(掌握) 65. 软件测试的目的是什么(掌握) 66. 软件测试的依据是什么(掌握) 67.软件需求的类型及软件需求分析 ...

  5. 千锋web前端教学知识点记录及个人理解4

    WEB前端知识点记录(84-109集) 第八十四集-relative相对定位 第八十五集-absolute绝对定位 第八十六集-fixed和sticky及zlndex 第八十七集-定位实现下拉菜单 课 ...

  6. 测试开发知识点整理(一)

    Java基础和数据库 计算机基础 1.计算机常识 2.计算机基础知识(了解) 3.计算机网络知识(了解) 编程入门 4.Java基础 5. eclipse工具 6. maven工具 7. Java S ...

  7. C++部分知识点记录

    文章目录 反问 为什么想要加入国微芯? 自己的优势/岗位匹配度在哪? EDA(电子设计自动化) 前言 <C++ Primer>知识点记录 1.声明一个返回数组指针的函数(P205) 2.头 ...

  8. JavaScript基础实战知识点记录及个人理解2

    JavaScript基础&实战知识点记录(26-45集) 第二十六集-运算符的优先级 第二十七集-代码块 第二十八.二十九.三十.三十一.三十二集-if语句 练习1 练习2 练习3 第三十三. ...

  9. javaweb基础知识点记录1

    javaweb基础知识点记录 1.当我们通过在浏览器的输入栏中直接输入网址的方式访问网页的时候,浏览器采用的就是GET方法向服务器获取资源. 2.我们可以将Servlet看做是嵌套了HTML代码的ja ...

最新文章

  1. python好找工作吗2017-2017,再来聊一聊Python,未来发展怎样?
  2. 分享你的见解与经验|RocketMQ Summit 2022 议题征集中
  3. 阿里云容器网络文件系统 CNFS 1.0 发布,体验云原生时代的容器共享存储
  4. SAP Spartacus里使用injection token提供默认配置的一个例子
  5. DNN模型训练词向量原理
  6. Log4j 2漏洞(CVE-2021-44228)的快速响应
  7. windows睡眠(休眠)唤醒助手_Windows快速启动背后的功臣:休眠
  8. (13)Verilog HDL变量:memory型
  9. Python课程期末考试编程题自动批卷原理与实现模板
  10. Mac OS 上配置java开发环境
  11. visual studio code(vscode)的使用(快捷键)
  12. [Linux] - 网速测试命令
  13. [转帖]任正非管理思想
  14. 插入参考文献时,本该显示为[1],但显示了{Zhao,2017,#253},解决方法
  15. Error: The required parameter ‘channelID‘ is empty. Rerun the command with -C flag
  16. Java环境下运行fastqc_质控软件fastQC的安装及用法
  17. android 后台运行service实现和后台的持续交互
  18. ubuntu破解密码方法
  19. 在线文库系统 文档在线预览 文库分享网站
  20. CTU Open Contest 2016 Suspicious Samples(单调队列)

热门文章

  1. 飞信2010分析 – 给离线好友发送消息
  2. BOOST THREAD
  3. oracle create unique index,ORA-01452: cannot CREATE UNIQUE INDEX; duplicate keys found
  4. Cesium可视域分析 不用修改源码
  5. 因为我是姑娘,所以不想像你一样安逸生活
  6. 在诗和远方中感受别样科技魅力,一次带上英得尔车载冰箱的自驾之旅!
  7. 论文投稿指南——中文核心期刊推荐(机械、仪表工业2)
  8. 运动规划入门 | 3. 白话PRM,从原理到Matlab实现
  9. 《最终幻想》的渲染技术
  10. 小米2S TWRP 3.0.2-0 最新版Recovery