开发工具:STS
前言:
shiro,一套简单灵活的安全权限管理框架。
把所有对外暴露的服务API都看作是一种资源,那么shiro就是负责控制哪些可以获得资源,哪些不能获取。
一个比较不错的教程:https://www.w3cschool.cn/shiro/
一个简单的小实例:
1.引入依赖
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4 <modelVersion>4.0.0</modelVersion> 5 6 <groupId>com.xm</groupId> 7 <artifactId>springboot_rbac</artifactId> 8 <version>0.0.1-SNAPSHOT</version> 9 <packaging>jar</packaging> 10 11 <name>springboot_rbac</name> 12 <description>This is a Web about springcloud</description> 13 14 <parent> 15 <groupId>org.springframework.boot</groupId> 16 <artifactId>spring-boot-starter-parent</artifactId> 17 <version>1.5.15.RELEASE</version> 18 <relativePath/> <!-- lookup parent from repository --> 19 </parent> 20 21 <properties> 22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 23 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 24 <java.version>1.8</java.version> 25 </properties> 26 27 <dependencies> 28 <dependency> 29 <groupId>org.springframework.boot</groupId> 30 <artifactId>spring-boot-starter-web</artifactId> 31 </dependency> 32 33 <dependency> 34 <groupId>org.springframework.boot</groupId> 35 <artifactId>spring-boot-starter-test</artifactId> 36 <scope>test</scope> 37 </dependency> 38 <dependency> 39 <groupId>org.apache.shiro</groupId> 40 <artifactId>shiro-spring</artifactId> 41 <version>1.2.2</version> 42 </dependency> 43 <!-- 配置shiro注解,需要用到aop --> 44 <dependency> 45 <groupId>org.springframework.boot</groupId> 46 <artifactId>spring-boot-starter-aop</artifactId> 47 </dependency> 48 </dependencies> 49 50 <build> 51 <plugins> 52 <plugin> 53 <groupId>org.springframework.boot</groupId> 54 <artifactId>spring-boot-maven-plugin</artifactId> 55 </plugin> 56 </plugins> 57 </build> 58 59 60 </project>
2.配置文件application.yml
1 spring.aop.proxy-target-class=true
3.realm
1 package com.xm.shiro.rbac; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 import org.apache.shiro.authc.AccountException; 7 import org.apache.shiro.authc.AuthenticationException; 8 import org.apache.shiro.authc.AuthenticationInfo; 9 import org.apache.shiro.authc.AuthenticationToken; 10 import org.apache.shiro.authc.SimpleAuthenticationInfo; 11 import org.apache.shiro.authc.UsernamePasswordToken; 12 import org.apache.shiro.authz.AuthorizationInfo; 13 import org.apache.shiro.authz.SimpleAuthorizationInfo; 14 import org.apache.shiro.realm.AuthorizingRealm; 15 import org.apache.shiro.subject.PrincipalCollection; 16 17 public class MyRealm extends AuthorizingRealm { 18 19 String getRoles() { 20 System.out.println("查找权限!"); 21 return "sun"; 22 } 23 24 /** 25 * 角色、权限认证 26 */ 27 @Override 28 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { 29 SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(); 30 //添加角色 31 info.addRole(getRoles()); 32 //添加权限 33 //info.addStringPermission("hello"); 34 return info; 35 } 36 37 /** 38 * 身份认证 39 */ 40 @Override 41 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 42 43 UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token; 44 String password = new String(usernamePasswordToken.getPassword()); 45 if(usernamePasswordToken.getUsername().equals("admin") && password.equals("123456")) { 46 Map<String, Object> user = new HashMap<>(); 47 user.put("username", "admin"); 48 user.put("password", "123456"); 49 return new SimpleAuthenticationInfo(user, user.get("password").toString(), this.getName()); 50 } else { 51 throw new AccountException("帐号或密码不正确!"); 52 } 53 } 54 }
4.配置shiro
1 package com.xm.shiro.rbac; 2 3 import java.util.LinkedHashMap; 4 import java.util.Map; 5 6 import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; 7 import org.apache.shiro.spring.web.ShiroFilterFactoryBean; 8 import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 9 import org.springframework.context.annotation.Bean; 10 import org.springframework.context.annotation.Configuration; 11 import org.apache.shiro.mgt.SecurityManager; 12 13 @Configuration 14 public class ShiroConfig { 15 16 @Bean 17 public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { 18 ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); 19 20 // 必须设置 SecurityManager 21 shiroFilterFactoryBean.setSecurityManager(securityManager); 22 23 // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 24 shiroFilterFactoryBean.setLoginUrl("/login"); 25 26 // 拦截器. 27 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); 28 // 配置不会被拦截的链接 顺序判断 29 filterChainDefinitionMap.put("/static/**", "anon"); 30 filterChainDefinitionMap.put("/doLogin/**", "anon"); 31 32 // <!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了; 33 // <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问--> 34 filterChainDefinitionMap.put("/**", "authc"); 35 36 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); 37 System.out.println("Shiro拦截器工厂类注入成功"); 38 return shiroFilterFactoryBean; 39 } 40 41 /** 42 * 注入MyRealm 43 * @return 44 */ 45 @Bean 46 public SecurityManager securityManager() { 47 DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 48 // 设置realm. 49 securityManager.setRealm(myShiroRealm()); 50 return securityManager; 51 } 52 53 /** 54 * 配置注解 55 * @param securityManager 56 * @return 57 */ 58 @Bean 59 public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { 60 AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor 61 = new AuthorizationAttributeSourceAdvisor(); 62 authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); 63 return authorizationAttributeSourceAdvisor; 64 } 65 66 public MyRealm myShiroRealm() { 67 return new MyRealm(); 68 } 69 70 }
5.controller
注解:
常用的就这两种
(1)@RequiresPermissions("hello") =>是否具有hello权限
(2)@@RequiresRoles("sun")=>是否有sun角色
1 package com.xm.shiro.controller; 2 3 import org.apache.shiro.SecurityUtils; 4 import org.apache.shiro.authc.AuthenticationException; 5 import org.apache.shiro.authc.IncorrectCredentialsException; 6 import org.apache.shiro.authc.UsernamePasswordToken; 7 import org.apache.shiro.authz.annotation.RequiresPermissions; 8 import org.apache.shiro.subject.Subject; 9 import org.springframework.web.bind.annotation.GetMapping; 10 import org.springframework.web.bind.annotation.PathVariable; 11 import org.springframework.web.bind.annotation.RequestMapping; 12 import org.springframework.web.bind.annotation.RestController; 13 14 @RestController 15 public class UserController { 16 17 @RequiresPermissions("hello") 18 @GetMapping("/hello") 19 public String hello() { 20 return "Hello Shiro!"; 21 } 22 23 @GetMapping("/login") 24 public String login() { 25 return "权限管理"; 26 } 27 28 @GetMapping("/doLogin/{username}/{password}") 29 public String doLogin(@PathVariable("username") String username,@PathVariable("password") String password) { 30 UsernamePasswordToken token = new UsernamePasswordToken(username, password); 31 Subject currentUser = SecurityUtils.getSubject(); 32 try { 33 currentUser.login(token); 34 //此步将 调用realm的认证方法 35 } catch(IncorrectCredentialsException e){ 36 //这最好把 所有的 异常类型都背会 37 return "密码错误"; 38 } catch (AuthenticationException e) { 39 return "登录失败"; 40 } 41 42 currentUser.hasRole("sun"); 43 currentUser.hasRole("sun"); 44 currentUser.hasRole("sun"); 45 currentUser.hasRole("sun"); 46 return token.getPrincipal()+":登录成功"; 47 } 48 49 @GetMapping("/logout") 50 public String logout() { 51 Subject currentUser = SecurityUtils.getSubject(); 52 currentUser.logout(); 53 return "退出登录"; 54 } 55 56 @GetMapping("/noUnauthorized") 57 public String error() { 58 return "无权限"; 59 } 60 61 }