Shiro是Apache下的一个开源项目,我们称之为Apache Shiro。

它是一个很易用与Java项目的的安全框架,提供了认证、授权、加密、会话管理,与spring Security 一样都是做一个权限的安全框架,但是与Spring Security 相比,在于 Shiro 使用了比较简单易懂易于使用的授权方式。

shiro属于轻量级框架,相对于security简单的多,也没有security那么复杂。

所以我这里也是简单介绍一下shiro的使用。

其基本功能点如下图所示:

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

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

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

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

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

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

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

Testing提供测试支持;

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

Remember Me记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

记住一点,Shiro不会去维护用户、维护权限;这些需要我们自己去设计/提供;然后通过相应的接口注入给Shiro即可。

这里我就简单介绍一下 springboot 和 shiro 整合与基本使用。

  1)目录结构

2)需要的基础包:pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6.  
  7. <groupId>com.troy</groupId>
  8. <artifactId>springshiro</artifactId>
  9. <version>1.0-SNAPSHOT</version>
  10. <parent>
  11. <groupId>org.springframework.boot</groupId>
  12. <artifactId>spring-boot-starter-parent</artifactId>
  13. <version>1.5.6.RELEASE</version>
  14. </parent>
  15.  
  16. <dependencies>
  17. <dependency>
  18. <groupId>org.springframework.boot</groupId>
  19. <artifactId>spring-boot-starter-web</artifactId>
  20. <version>1.5.6.RELEASE</version>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework.boot</groupId>
  24. <artifactId>spring-boot-starter-data-jpa</artifactId>
  25. <version>1.5.6.RELEASE</version>
  26. </dependency>
  27. <dependency>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-autoconfigure</artifactId>
  30. <version>1.5.6.RELEASE</version>
  31. </dependency>
  32. <dependency>
  33. <groupId>mysql</groupId>
  34. <artifactId>mysql-connector-Java</artifactId>
  35. <version>5.1.9</version>
  36. </dependency>
  37. <dependency>
  38. <groupId>org.apache.shiro</groupId>
  39. <artifactId>shiro-spring</artifactId>
  40. <version>1.3.2</version>
  41. </dependency>
  42. <dependency>
  43. <groupId>com.alibaba</groupId>
  44. <artifactId>druid</artifactId>
  45. <version>1.1.4</version>
  46. </dependency>
  47. </dependencies>
  48.  
  49. </project>

3)基本配置application.yml

  1. server:
  2. port: 8082
  3. spring:
  4. datasource:
  5. driver-class-name: com.mysql.jdbc.Driver
  6. url: jdbc:mysql://localhost:3306/spring_shiro?useUnicode=true&amp;characterEncoding=UTF-8
  7. username: root
  8. password: root
  9. type: com.alibaba.druid.pool.DruidDataSource
  10. jpa:
  11. show-sql: true
  12. hibernate:
  13. ddl-auto: update
  14. http:
  15. encoding:
  16. charset: utf-8
  17. enabled: true

4)这里我们基本需要3个实体,用户,角色和权限

  (1) 角色:User.class

  1. @Entity
  2. public class User {
  3.  
  4. @Id
  5. @GeneratedValue(strategy = GenerationType.AUTO)
  6. private Long id;
  7. @Column(unique = true)
  8. private String name;
  9. private Integer password;
  10. @OneToMany(cascade = CascadeType.ALL,mappedBy = "user")
  11. private List<Role> roles;
  12.  
  13. public Long getId() {
  14. return id;
  15. }
  16.  
  17. public void setId(Long id) {
  18. this.id = id;
  19. }
  20.  
  21. public String getName() {
  22. return name;
  23. }
  24.  
  25. public void setName(String name) {
  26. this.name = name;
  27. }
  28.  
  29. public List<Role> getRoles() {
  30. return roles;
  31. }
  32.  
  33. public void setRoles(List<Role> roles) {
  34. this.roles = roles;
  35. }
  36.  
  37. public Integer getPassword() {
  38. return password;
  39. }
  40.  
  41. public void setPassword(Integer password) {
  42. this.password = password;
  43. }
  44. }

  注:这里我只考虑一个用户对多个角色,不考虑多对多的关系

  

      (2)角色:Role.class

  1. @Entity
  2. public class Role {
  3.  
  4. @Id
  5. @GeneratedValue(strategy = GenerationType.AUTO)
  6. private Long id;
  7. private String roleName;
  8. @ManyToOne(fetch = FetchType.EAGER)
  9. private User user;
  10. @OneToMany(cascade = CascadeType.ALL,mappedBy = "role")
  11. private List<Permission> permissions;
  12.  
  13. public Long getId() {
  14. return id;
  15. }
  16.  
  17. public void setId(Long id) {
  18. this.id = id;
  19. }
  20.  
  21. public String getRoleName() {
  22. return roleName;
  23. }
  24.  
  25. public void setRoleName(String roleName) {
  26. this.roleName = roleName;
  27. }
  28.  
  29. public User getUser() {
  30. return user;
  31. }
  32.  
  33. public void setUser(User user) {
  34. this.user = user;
  35. }
  36.  
  37. public List<Permission> getPermissions() {
  38. return permissions;
  39. }
  40.  
  41. public void setPermissions(List<Permission> permissions) {
  42. this.permissions = permissions;
  43. }
  44. }

 

  (3)权限:Permission.class

  1. @Entity
  2. public class Permission {
  3.  
  4. @Id
  5. @GeneratedValue(strategy = GenerationType.AUTO)
  6. private Long id;
  7. private String permission;
  8. @ManyToOne(fetch = FetchType.EAGER)
  9. private Role role;
  10.  
  11. public Long getId() {
  12. return id;
  13. }
  14.  
  15. public void setId(Long id) {
  16. this.id = id;
  17. }
  18.  
  19. public String getPermission() {
  20. return permission;
  21. }
  22.  
  23. public void setPermission(String permission) {
  24. this.permission = permission;
  25. }
  26.  
  27. public Role getRole() {
  28. return role;
  29. }
  30.  
  31. public void setRole(Role role) {
  32. this.role = role;
  33. }
  34. }

5)然后就是配置对应的验证,以及过滤条件

  (1) 验证,以及权限的添加MyShiroRealm.class

  1. //实现AuthorizingRealm接口用户用户认证
  2. public class MyShiroRealm extends AuthorizingRealm{
  3.  
  4. //用于用户查询
  5. @Autowired
  6. private ILoginService loginService;
  7.  
  8. //角色权限和对应权限添加
  9. @Override
  10. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
  11. //获取登录用户名
  12. String name= (String) principalCollection.getPrimaryPrincipal();
  13. //查询用户名称
  14. User user = loginService.findByName(name);
  15. //添加角色和权限
  16. SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
  17. for (Role role:user.getRoles()) {
  18. //添加角色
  19. simpleAuthorizationInfo.addRole(role.getRoleName());
  20. for (Permission permission:role.getPermissions()) {
  21. //添加权限
  22. simpleAuthorizationInfo.addStringPermission(permission.getPermission());
  23. }
  24. }
  25. return simpleAuthorizationInfo;
  26. }
  27.  
  28. //用户认证
  29. @Override
  30. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
  31. //加这一步的目的是在Post请求的时候会先进认证,然后在到请求
  32. if (authenticationToken.getPrincipal() == null) {
  33. return null;
  34. }
  35. //获取用户信息
  36. String name = authenticationToken.getPrincipal().toString();
  37. User user = loginService.findByName(name);
  38. if (user == null) {
  39. //这里返回后会报出对应异常
  40. return null;
  41. } else {
  42. //这里验证authenticationToken和simpleAuthenticationInfo的信息
  43. SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, user.getPassword().toString(), getName());
  44. return simpleAuthenticationInfo;
  45. }
  46. }
  47. }

  (2)过滤配置:ShiroConfiguration.class

  1. @Configuration
  2. public class ShiroConfiguration {
  3.  
  4. //将自己的验证方式加入容器
  5. @Bean
  6. public MyShiroRealm myShiroRealm() {
  7. MyShiroRealm myShiroRealm = new MyShiroRealm();
  8. return myShiroRealm;
  9. }
  10.  
  11. //权限管理,配置主要是Realm的管理认证
  12. @Bean
  13. public SecurityManager securityManager() {
  14. DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
  15. securityManager.setRealm(myShiroRealm());
  16. return securityManager;
  17. }
  18.  
  19. //Filter工厂,设置对应的过滤条件和跳转条件
  20. @Bean
  21. public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
  22. ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
  23. shiroFilterFactoryBean.setSecurityManager(securityManager);
  24. Map<String,String> map = new HashMap<String, String>();
  25. //登出
  26. map.put("/logout","logout");
  27. //对所有用户认证
  28. map.put("/**","authc");
  29. //登录
  30. shiroFilterFactoryBean.setLoginUrl("/login");
  31. //首页
  32. shiroFilterFactoryBean.setSuccessUrl("/index");
  33. //错误页面,认证不通过跳转
  34. shiroFilterFactoryBean.setUnauthorizedUrl("/error");
  35. shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
  36. return shiroFilterFactoryBean;
  37. }
  38.  
  39. //加入注解的使用,不加入这个注解不生效
  40. @Bean
  41. public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
  42. AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
  43. authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
  44. return authorizationAttributeSourceAdvisor;
  45. }
  46. }

6)接下来就是数据访问层、业务层、以及控制层

  (1) 数据层:BaseRepository.class,UserRepository.class,RoleRepository.class

  1. @NoRepositoryBean
  2. public interface BaseRepository<T,I extends Serializable> extends PagingAndSortingRepository<T,I>,JpaSpecificationExecutor<T>{
  3.  
  4. }
  1. public interface UserRepository extends BaseRepository<User,Long>{
  2. User findByName(String name);
  3. }
  1. public interface RoleRepository extends BaseRepository<Role,Long> {
  2.  
  3. }

  (2)业务层:LoginServiceImpl.class

  1. @Service
  2. @Transactional
  3. public class LoginServiceImpl implements ILoginService {
  4.  
  5. @Autowired
  6. private UserRepository userRepository;
  7. @Autowired
  8. private RoleRepository roleRepository;
  9.  
  10. //添加用户
  11. @Override
  12. public User addUser(Map<String, Object> map) {
  13. User user = new User();
  14. user.setName(map.get("username").toString());
  15. user.setPassword(Integer.valueOf(map.get("password").toString()));
  16. userRepository.save(user);
  17. return user;
  18. }
  19.  
  20. //添加角色
  21. @Override
  22. public Role addRole(Map<String, Object> map) {
  23. User user = userRepository.findOne(Long.valueOf(map.get("userId").toString()));
  24. Role role = new Role();
  25. role.setRoleName(map.get("roleName").toString());
  26. role.setUser(user);
  27. Permission permission1 = new Permission();
  28. permission1.setPermission("create");
  29. permission1.setRole(role);
  30. Permission permission2 = new Permission();
  31. permission2.setPermission("update");
  32. permission2.setRole(role);
  33. List<Permission> permissions = new ArrayList<Permission>();
  34. permissions.add(permission1);
  35. permissions.add(permission2);
  36. role.setPermissions(permissions);
  37. roleRepository.save(role);
  38. return role;
  39. }
  40.  
  41. //查询用户通过用户名
  42. @Override
  43. public User findByName(String name) {
  44. return userRepository.findByName(name);
  45. }
  46. }

  (3)控制层:LoginResource.class

  1. @RestController
  2. public class LoginResource {
  3.  
  4. @Autowired
  5. private ILoginService loginService;
  6.  
  7. //退出的时候是get请求,主要是用于退出
  8. @RequestMapping(value = "/login",method = RequestMethod.GET)
  9. public String login(){
  10. return "login";
  11. }
  12.  
  13. //post登录
  14. @RequestMapping(value = "/login",method = RequestMethod.POST)
  15. public String login(@RequestBody Map map){
  16. //添加用户认证信息
  17. Subject subject = SecurityUtils.getSubject();
  18. UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
  19. map.get("username").toString(),
  20. map.get("password").toString());
  21. //进行验证,这里可以捕获异常,然后返回对应信息
  22. subject.login(usernamePasswordToken);
  23. return "login";
  24. }
  25.  
  26. @RequestMapping(value = "/index")
  27. public String index(){
  28. return "index";
  29. }
  30.  
  31. //登出
  32. @RequestMapping(value = "/logout")
  33. public String logout(){
  34. return "logout";
  35. }
  36.  
  37. //错误页面展示
  38. @RequestMapping(value = "/error",method = RequestMethod.POST)
  39. public String error(){
  40. return "error ok!";
  41. }
  42.  
  43. //数据初始化
  44. @RequestMapping(value = "/addUser")
  45. public String addUser(@RequestBody Map<String,Object> map){
  46. User user = loginService.addUser(map);
  47. return "addUser is ok! \n" + user;
  48. }
  49.  
  50. //角色初始化
  51. @RequestMapping(value = "/addRole")
  52. public String addRole(@RequestBody Map<String,Object> map){
  53. Role role = loginService.addRole(map);
  54. return "addRole is ok! \n" + role;
  55. }
  56.  
  57. //注解的使用
  58. @RequiresRoles("admin")
  59. @RequiresPermissions("create")
  60. @RequestMapping(value = "/create")
  61. public String create(){
  62. return "Create success!";
  63. }
  64. }

注:这里对于注解的使用,在最后一个很重要!

7)shiro的使用基本上就是这样子了,主要是权限的控制,其他的主要是做跳转和切换使用

 8)最后配上数据库信息:结合控制层观看

user:

role:

permission:

在 springboot 中如何整合 shiro 应用 ?的更多相关文章

  1. SpringBoot 优雅的整合 Shiro

    Apache Shiro是一个功能强大且易于使用的Java安全框架,可执行身份验证,授权,加密和会话管理.借助Shiro易于理解的API,您可以快速轻松地保护任何应用程序 - 从最小的移动应用程序到最 ...

  2. redis(Springboot中封装整合redis,java程序如何操作redis的5种基本数据类型)

    平常测试redis操作命令,可能用的是cmd窗口 操作redis,记录一下 java程序操作reids, 操作redis的方法 可以用Jedis ,在springboot 提供了两种 方法操作 Red ...

  3. SpringBoot学习:整合shiro(身份认证和权限认证),使用EhCache缓存

    项目下载地址:http://download.csdn.NET/detail/aqsunkai/9805821 (一)在pom.xml中添加依赖: <properties> <shi ...

  4. SpringBoot学习:整合shiro自动登录功能(rememberMe记住我功能)

    首先在shiro配置类中注入rememberMe管理器 /** * cookie对象; * rememberMeCookie()方法是设置Cookie的生成模版,比如cookie的name,cooki ...

  5. SpringBoot学习:整合shiro(rememberMe记住我后自动登录session失效解决办法)

    项目下载地址:http://download.csdn.NET/detail/aqsunkai/9805821 定义一个拦截器,判断用户是通过记住我登录时,查询数据库后台自动登录,同时把用户放入ses ...

  6. SpringBoot学习:整合shiro(验证码功能和登录次数限制功能)

    项目下载地址:http://download.csdn.NET/detail/aqsunkai/9805821 (一)验证码 首先login.jsp里增加了获取验证码图片的标签: <body s ...

  7. SpringBoot学习:整合shiro(rememberMe记住我功能)

    项目下载地址:http://download.csdn.NET/detail/aqsunkai/9805821 首先在shiro配置类中注入rememberMe管理器 /** * cookie对象; ...

  8. 关于Springboot中dubbo整合注意的误区(不对之处请指出)

    这是我的客户端配置! 这是生产的配置, 首先注意一下 scan   我之前尝试这样的客户端配置 然后  果断客户端不能注册接口 @Reference(version="1.0") ...

  9. SpringBoot 中aop整合方法执行日志

    今天事情不多, 处理完手中的事边想着捣鼓一下AOP, 着手开始写才发现, 多久不用, 自己已经忘得差不多了, 捣鼓半天之后, 慢慢整出这个小demo,以便于以后查阅回顾 1 .先创建一个注解, 用来作 ...

随机推荐

  1. 学习笔记20151211——AXI4 STREAM DATA FIFO

    AXI4 STREAM DATA FIFO是输入输出接口均为AXIS接口的数据缓存器,和其他fifo一样是先进先出形式.可以在跨时钟域的应用中用于数据缓冲,避免亚稳态出现.支持数据的分割和数据拼接.在 ...

  2. CASIO 5800P计算器游戏--猜数字游戏

    CASIO 5800P 计算器游戏--猜数字游戏原代码 我编的计算器小游戏--猜数字游戏 LbI I↙ "xxGUESS NUMBERxx xPROGRAMMER:JCHx -------- ...

  3. 建造者模式 build

    引出建造者模式: package com.disign.build; /** * Created by zhen on 2017-05-19. */ public class BuildPersonT ...

  4. MVC项目使用Oracle数据库运行提示:找不到请求的 .Net Framework Data Provider。可能没有安装

    MVC项目使用Entity Framework针对Oracle数据库进行开发时,由于Oracle官方网站一般建议开发者在64位操作系统中使用32位ODP.Net进行开发.在进行程序编码的时候不会有问题 ...

  5. 通过VNC连接远程服务器,然后登陆服务器上的虚拟机,出现键盘输入问题的解决方法

    前几天由于要在服务器上装一个虚拟机,然后就选择了vmware workstation,装好之后,进入虚拟机中的centOS系统,发现键盘上的Cpas Lock键不起作用,按下之后还是输入小写,而且按住 ...

  6. Sqlserver 按照时间段统计数据

    WITH t1 ( [hour], title ) , ' 0:00:00--- 1:00:00' UNION ALL , ' 1:00:00--- 2:00:00' UNION ALL , ' 2: ...

  7. Django 之 Ajax

    此次主要是做省市区的三级联动. 环境:django 1.10 1. urls.py # coding:utf-8 from django.conf.urls import url import vie ...

  8. Linux udhcp client (udhcpc) get IP at anytime

    /*************************************************************************************** * Linux udh ...

  9. Convex 一道阿姆斯特朗回旋好题

    2001年5月8日,阿姆斯特朗(Armstrong, 1929-2013) 教授发明了一种名为“阿姆斯特朗回旋加速喷气式阿姆斯特朗加密”的加密算法,算法从未公开,直至2013阿姆斯特朗教授逝世后,其生 ...

  10. 使用ajax提交form表单,包括ajax文件上传 转http://www.cnblogs.com/zhuxiaojie/p/4783939.html

    使用ajax提交form表单,包括ajax文件上传 前言 使用ajax请求数据,很多人都会,比如说: $.post(path,{data:data},function(data){ ... },&qu ...