shiro框架的简单介绍以及使用(一)

写给我大聂哥

1.什么是shiro

shiro框架的简单介绍以及使用(一)

2.1主要模块

  • Authentication:认证/登录
    认证简单来说就是登录,判断用户的账号密码是否正确,有没有这个用户。
  • Authorization:授权与权限验证。
    授权就是给与用户某个权限,权限验证就是判断这个用户有没有权限干这个事 。
    例如:你打LOL选了瞎子,你能看到所有皮肤,但是你没买的你用不了,为什么呢?
    因为你没这个权限呗,你买了我就给你加上这个权限,你就能用了。
  • SessionManagement:会话管理
    会话就是说用户访问应用时保持的连接关系,能够识别出当前访问的用户是谁。
  • Cryptography:加密
    加密就是加密,字面意思,使用密码算法保持数据安全,同时仍然易于使用。

2.2次要模块

官方说法

  • Web支持:Shiro的Web支持API可帮助轻松保护Web应用程序。
  • 缓存:缓存是Apache Shiro API的第一层公民,可确保安全操作保持快速有效。
  • 并发性:Apache Shiro的并发功能支持多线程应用程序。
  • 测试:测试支持可帮助您编写单元测试和集成测试,并确保您的代码将按预期进行保护。
  • “运行方式”:一种功能,允许用户采用其他用户的身份(如果允许),有时在管理方案中很有用。
  • “记住我”:在整个会话中记住用户的身份,因此他们只需要在必要时登录。

注意: Shiro不会去维护用户、维护权限,这些需要我们自己去设计/提供,然后通过相应的接口注入给Shiro

3.shiro高层概念

shiro框架的简单介绍以及使用(一)

3.1三个主要概念

  • Subject
    代表当前用户,用户的抽象概念,它会被绑定到SecurityManager,所有的交互都由SecurityManager来完成
    简单来说相当于一个实体类,它本身没有功能性,只是起到一个存储数据的作用。
  • SecurityManager
    SecurityManager是shiro的核心,所有的安全交互都在这个里面完成。
  • Realm
    Realm是一个域,SecurityManager在Realm中获取安全数据,如用户是否合法,是否有权限访问
    也就是说上面描述的两个模块Authentication和Authorization都是在这个概念里面。

3.2从上面这个概念描述我们可以看出运行的顺序

用户登录->Subject->SecurityManager->Realm进行验证。
而Realm我们上面也说了Authentication和Authorization都是在这个概念里面,那么这两个模块先运行谁呢?
那肯定是Authentication登录认证啊,你不登录去查Authorization权限干嘛咧?看有没有权限登录?你搁这想屁吃呢。

4.shiro实现登录

4.1 maven配置

 <dependencies>         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-web</artifactId>         </dependency>          <dependency>             <groupId>org.springframework</groupId>             <artifactId>spring-jdbc</artifactId>             <version>4.3.10.RELEASE</version>         </dependency>          <dependency>             <groupId>org.apache.shiro</groupId>             <artifactId>shiro-spring</artifactId>             <version>1.3.2</version>         </dependency>          <!-- MySQL 连接驱动依赖 -->         <dependency>             <groupId>mysql</groupId>             <artifactId>mysql-connector-java</artifactId>             <version>5.1.46</version>         </dependency>          <dependency>             <groupId>com.alibaba</groupId>             <artifactId>druid-spring-boot-starter</artifactId>             <version>1.1.10</version>         </dependency>          <!-- spring boot 热部署 stat-->         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-devtools</artifactId>             <optional>true</optional>         </dependency>         <!-- spring boot 热部署 end -->         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-test</artifactId>             <scope>test</scope>             <exclusions>                 <exclusion>                     <groupId>org.junit.vintage</groupId>                     <artifactId>junit-vintage-engine</artifactId>                 </exclusion>             </exclusions>         </dependency>     </dependencies>      <build>         <plugins>             <plugin>                 <groupId>org.springframework.boot</groupId>                 <artifactId>spring-boot-maven-plugin</artifactId>                 <configuration>                 <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->             </configuration>             </plugin>         </plugins>     </build>  

4.2 Jpackage com.lzl.practice.Util; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.List; public class JacksonUtil { public static String parseString(String body, String field) { ObjectMapper mapper = new ObjectMapper(); JsonNode node = null; try { node = mapper.readTree(body); JsonNode leaf = node.get(field); if (leaf != null) return leaf.asText(); } catch (IOException e) { e.printStackTrace(); } return null; } public static List<String> parseStringList(String body, String field) { ObjectMapper mapper = new ObjectMapper(); JsonNode node = null; try { node = mapper.readTree(body); JsonNode leaf = node.get(field); if (leaf != null) return mapper.convertValue(leaf, new TypeReference<List<String>>() { }); } catch (IOException e) { e.printStackTrace(); } return null; } public static Integer parseInteger(String body, String field) { ObjectMapper mapper = new ObjectMapper(); JsonNode node = null; try { node = mapper.readTree(body); JsonNode leaf = node.get(field); if (leaf != null) return leaf.asInt(); } catch (IOException e) { e.printStackTrace(); } return null; } public static List<Integer> parseIntegerList(String body, String field) { ObjectMapper mapper = new ObjectMapper(); JsonNode node = null; try { node = mapper.readTree(body); JsonNode leaf = node.get(field); if (leaf != null) return mapper.convertValue(leaf, new TypeReference<List<Integer>>() { }); } catch (IOException e) { e.printStackTrace(); } return null; } public static Boolean parseBoolean(String body, String field) { ObjectMapper mapper = new ObjectMapper(); JsonNode node = null; try { node = mapper.readTree(body); JsonNode leaf = node.get(field); if (leaf != null) return leaf.asBoolean(); } catch (IOException e) { e.printStackTrace(); } return null; } public static Short parseShort(String body, String field) { ObjectMapper mapper = new ObjectMapper(); JsonNode node = null; try { node = mapper.readTree(body); JsonNode leaf = node.get(field); if (leaf != null) { Integer value = leaf.asInt(); return value.shortValue(); } } catch (IOException e) { e.printStackTrace(); } return null; } public static Byte parseByte(String body, String field) { ObjectMapper mapper = new ObjectMapper(); JsonNode node = null; try { node = mapper.readTree(body); JsonNode leaf = node.get(field); if (leaf != null) { Integer value = leaf.asInt(); return value.byteValue(); } } catch (IOException e) { e.printStackTrace(); } return null; } public static <T> T parseObject(String body, String field, Class<T> clazz) { ObjectMapper mapper = new ObjectMapper(); JsonNode node = null; try { node = mapper.readTree(body); node = node.get(field); return mapper.treeToValue(node, clazz); } catch (IOException e) { e.printStackTrace(); } return null; } public static Object toNode(String json) { if (json == null) { return null; } ObjectMapper mapper = new ObjectMapper(); try { JsonNode jsonNode = mapper.readTree(json); return jsonNode; } catch (IOException e) { e.printStackTrace(); } return null; } }

4.3 配置shiroConfig

@Configuration public class ShiroConfig {      //将自己的登录验证方式加入容器     //直接写return new AuthRealm()也是一样的,但是不要在下面的securityManager()方法中直接new AuthRealm()     //直接new的话我只能说好家伙,自己实例化对象之后该类就不会在springboot容器中了,     //这样就不能在AuthRealm类中autowired了     @Bean     public Realm AuthRealm() {         AuthRealm authRealm = new AuthRealm();         return authRealm;     }       //将自己配置的AuthRealm配置到securityManager中     @Bean     public DefaultWebSecurityManager securityManager() {         DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();         securityManager.setRealm(AuthRealm());         return securityManager;     }      //Filter工厂,设置对应的过滤条件和跳转条件     @Bean     public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {         ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();         shiroFilterFactoryBean.setSecurityManager(securityManager);         Map<String,String> map = new HashMap<String, String>();         //登出         map.put("/logout","logout");         //对所有用户认证         map.put("/**","authc");          //首页         shiroFilterFactoryBean.setSuccessUrl("/index");         //错误页面,认证不通过跳转         shiroFilterFactoryBean.setUnauthorizedUrl("/auth/error");         shiroFilterFactoryBean.setLoginUrl("/auth/login");//登录         shiroFilterFactoryBean.setSuccessUrl("/auth/index");          shiroFilterFactoryBean.setUnauthorizedUrl("/auth/403");         shiroFilterFactoryBean.setFilterChainDefinitionMap(map);         return shiroFilterFactoryBean;     }      //开启代码支持     @Bean     public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {         AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();         authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);         return authorizationAttributeSourceAdvisor;     } } 

shirFilter工厂里面的的logout、authc、anon都是拦截器。
拦截器链名定义

名字 名称 说明
anon 匿名拦截器 不需要登录就能访问,一般用于静态资源,或者移动端接口
authc 登录拦截器 需要登录认证才能访问的资源
user 用户拦截器 用户拦截器,用户已经身份验证 / 记住我登录的都可;
logout 登出拦截器 用户登出拦截器

4.4 配置AuthRealm

public class AuthRealm extends AuthorizingRealm {      /***      * @Description: 这块是授权配置      * @Param: [principalCollection]      * @return: org.apache.shiro.authz.AuthorizationInfo      * @Author: lizelin      * @Date: 2021/5/13 0013 1:25     */     @Override     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {         SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();         return info;     }          /***      * @Description: 这块是登录验证配置      * @Param: [token]      * @return: org.apache.shiro.authc.AuthenticationInfo      * @Author: lizelin      * @Date: 2021/5/13 0013 1:25     */     @Override     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {         //AuthenticationToken转成UsernamePasswordToken这样可以直接拿到用户名和密码         UsernamePasswordToken upToken = (UsernamePasswordToken) token;         String username = upToken.getUsername();         //判断用户名是否为aaa否则抛出异常完事密码错误         if(!username.equals("aaa")){             throw new UnknownAccountException("用户错误");         }         return new SimpleAuthenticationInfo(upToken.getUsername(), upToken.getPassword(), "ShiroReaml");     } 

这里我只写了登录验证配置,判断用户名是否正确,简单测试一下,加入授权和密码验证明天再说今天困了。

4.5 配置controller测试

 @RestController @RequestMapping("/auth") public class AuthController {      /**     * @Description: 登录验证     * @Param: [body]     * @return: java.lang.Object     * @Author: Mr.Wang     * @Date: 2021/5/13 0013 1:50     */     @PostMapping("/login")     public Object login(@RequestBody String body) {         String username = JacksonUtil.parseString(body, "username");         String password = JacksonUtil.parseString(body, "password");         //获取Subject         Subject subject = SecurityUtils.getSubject();         try {             //登录测试,就这一行代码             subject.login(new UsernamePasswordToken(username, password));         } catch (UnknownAccountException uae) {             return "用户帐号或密码不正确";         } catch (LockedAccountException lae) {             return "用户帐号已锁定不可用";         } catch (AuthenticationException ae) {             return "用户帐号已锁定不可用";         }         return "登录成功,账号名:"+username;     }      @PostMapping("/testAuthc")     public Object testAuthc() {         return "testAuthc";     }          @GetMapping("/401")     public Object page401() {         return "401";     }      @GetMapping("/index")     public Object pageIndex() {         return "index";     }      @GetMapping("/403")     public Object page403() {         return "index";     }      @GetMapping("/error")     public Object error() {         return "error";     } }  

简单的测试环境就搭好了,完事我们去测试。

5.spring boot+shiro测试

5.1账号正确测试

shiro框架的简单介绍以及使用(一)
ok登录成功,测试没毛病。

5.2账号错误测试

shiro框架的简单介绍以及使用(一)
ok返回密码错误,测试没毛病。

5.3拦截器authc测试

shiro框架的简单介绍以及使用(一)

shiro框架的简单介绍以及使用(一)
ok返回地址是/auth/login,测试拦截没毛病。

简单的登陆用户名验证就完事了,然后写密码验证,权限,三方登录

版权声明:玥玥 发表于 2021-05-14 16:22:29。
转载请注明:shiro框架的简单介绍以及使用(一) | 女黑客导航