赞
踩
在做毕设系统的时候想要让我们的系统更加安全,并且看起来更加高大上,使用算法MD5,特学了shiro相关知识,首先什么是Shiro?
官方说法:Apache shiro是一个强大易用的开源安全框架,用于简化应用程序安全和加强其验证处理,以及控制访问控制行为,Apache shiro可以让帮助外面编写易于维护的安全和认证的实现,常用于web以及JavaEE的环境,其实说白了shiro就是一个通过过滤确定具体请求的URL是否允许访问,以及处理认证和授权的方法。
进一步了解shiro,我们可以先明确其基本功能
Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即 判断用 户是否能进行什么操作
Session Manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中
Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
Web Support:Web 支持,可以非常容易的集成到 Web 环境
Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,可以提高效率
Concurrency:Shiro 支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
Testing:提供测试支持;
Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了
原理: 从外部架构来看
subject代表当前“用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如机器人,网络爬虫等,与subject的所有交互都会委托给securityManager(安全管理器),subject相当于一个门面,securitymanager才是实际上的执行者,其管理所有的subject,是shiro的核心,他负责和shrio的其他组件进行交互交互,Realm(实际处理认证和授权工作的实体),shiro从Realm获取安全数据如角色,用户,权限,也就是说SecurityManager要验证用户身份,那么他需要从Realm获取相应的用户进行比较来确定用户的身份是否合法,也就是说需要从Realm中得到相应的用户信息进行验证用户能否进行操作
原理: 从内部架构来看
具体使用Shiro如何整合到我们SpringBoot项目中
- <!--shiro-->
- <dependency>
- <groupId>org.apache.shiro</groupId>
- <artifactId>shiro-spring-boot-web-starter</artifactId>
- <version>1.9.0</version>
- </dependency>
- spring:
- datasource:
- type: com.zaxxer.hikari.HikariDataSource
- driver-class-name: com.mysql.jdbc.Driver
- url: jdbc:mysql://127.0.0.1:3306/shirodb?serverTimezone=UTC&characterEncoding=utf-8&useSSL=false
- username: root
- password: 123456
- jackson:
- date-format: yyyy-MM-dd HH:mm:ss
- time-zone: GMT+8
- shiro:
- loginUrl: /myController/login
driver-class-name: com.mysql.cj.jdbc.Driver
- package com.shiro.entity;
-
- import lombok.AllArgsConstructor;
- import lombok.Data;
- import lombok.NoArgsConstructor;
-
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- public class User {
- private Integer id;
- private String name;
- private String pwd;
- private Integer rid;
- }
- package com.shiro.mapper;
-
- import com.baomidou.mybatisplus.core.mapper.BaseMapper;
- import com.shiro.entity.User;
- import org.springframework.stereotype.Repository;
-
- @Repository
- public interface UserMapper extends BaseMapper<User> {
- }
- package com.shiro.service;
-
- import com.shiro.entity.User;
- import com.shiro.mapper.UserMapper;
- import org.springframework.beans.factory.annotation.Autowired;
-
-
- public interface UserService {
- //用户登录
- User getUserInfoByName(String name);
- }
- package com.shiro.service.impl;
-
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import com.shiro.entity.User;
- import com.shiro.mapper.UserMapper;
- import com.shiro.service.UserService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
-
- @Service
- public class UserServiceImpl implements UserService {
- @Autowired
- private UserMapper userMapper;
- @Override
- public User getUserInfoByName(String name) {
- QueryWrapper<User> wrapper=new QueryWrapper<>();
- wrapper.eq("name",name);
- User user = userMapper.selectOne(wrapper);
- return user;
- }
- }
- package com.shiro.realm;
-
- import com.shiro.entity.User;
- import com.shiro.mapper.UserMapper;
- import com.shiro.service.UserService;
- import org.apache.shiro.authc.AuthenticationException;
- import org.apache.shiro.authc.AuthenticationInfo;
- import org.apache.shiro.authc.AuthenticationToken;
- import org.apache.shiro.authc.SimpleAuthenticationInfo;
- import org.apache.shiro.authz.AuthorizationInfo;
- import org.apache.shiro.realm.AuthorizingRealm;
- import org.apache.shiro.subject.PrincipalCollection;
- import org.apache.shiro.util.ByteSource;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
-
- @Component
- public class MyRealm extends AuthorizingRealm {
- @Autowired
- private UserService userService;
-
- //自定义授权方法:获取当前登录用户的角色、权限信息,返回给shiro用来进行授权认证
- @Override
- protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
- //1.创建对象,封装当前用户登录的角色、权限信息
- SimpleAuthenticationInfo info = new SimpleAuthenticationInfo();
- //2.存储角色
- // info.addRole("admin");
- //3.返回信息
- return null;
- }
-
- //自定义登录认证方法
- @Override
- protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
- //1.获取用户身份信息
- String name = authenticationToken.getPrincipal().toString();
- //2.调用业务层获取用户信息(数据库表中存的)
- User user = userService.getUserInfoByName(name);
- //3.非空判断将数据封装返回
- if (user != null) {
- AuthenticationInfo info = new SimpleAuthenticationInfo(
- authenticationToken.getPrincipal(),
- user.getPwd(),
- ByteSource.Util.bytes("salt"),
- authenticationToken.getPrincipal().toString()
- );
- return info;
- }
- return null;
- }
- }
- package com.shiro.config;
-
- import com.shiro.realm.MyRealm;
- import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
- import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
- import org.apache.shiro.web.mgt.CookieRememberMeManager;
- import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
- import org.apache.shiro.web.servlet.SimpleCookie;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
-
- @Configuration
- public class ShiroConfig {
- @Autowired
- private MyRealm myRealm;
- // private MyRealm2 myRealm2;
- //配置SecurityManager
- @Bean
- public DefaultWebSecurityManager defaultWebSecurityManager(){
- //1 创建 defaultWebSecurityManager 对象
- DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
- //2 创建加密对象,并设置相关属性
- HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
- //2.1 采用 md5 加密
- matcher.setHashAlgorithmName("md5");
- //2.2 迭代加密次数
- matcher.setHashIterations(3);
- //3 将加密对象存储到 myRealm 中
- myRealm.setCredentialsMatcher(matcher);
- //4 将 myRealm 存入 defaultWebSecurityManager 对象
- defaultWebSecurityManager.setRealm(myRealm);
- //设置remmerberMe
- defaultWebSecurityManager.setRememberMeManager(rememberMeManager());
- //5 返回
- return defaultWebSecurityManager;
- }
-
- //cookie 属性设置
- public SimpleCookie rememberMeCookie(){
- SimpleCookie cookie = new SimpleCookie("rememberMe");
- //设置跨域
- //cookie.setDomain(domain);
- cookie.setPath("/");
- cookie.setHttpOnly(true);
- cookie.setMaxAge(30*24*60*60);
- return cookie;
- }
- //创建 Shiro 的 cookie 管理对象
- public CookieRememberMeManager rememberMeManager(){
- CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
- cookieRememberMeManager.setCookie(rememberMeCookie());
- cookieRememberMeManager.setCipherKey("1234567890987654".getBytes());
- return cookieRememberMeManager;
- }
-
- //配置 Shiro 内置过滤器拦截范围
- @Bean
- public DefaultShiroFilterChainDefinition shiroFilterChainDefinition() {
- DefaultShiroFilterChainDefinition definition = new DefaultShiroFilterChainDefinition();
- //设置不认证可以访问的资源
- definition.addPathDefinition("/myController/userLogin", "anon");
- definition.addPathDefinition("/myController/login","anon");
- //配置登出过滤器
- definition.addPathDefinition("/logout","logout");
- //添加存在用户的过滤器(rememberMe)
- definition.addPathDefinition("/**","user");
- //设置需要进行登录认证的拦截范围
- definition.addPathDefinition("/**", "authc");
-
- return definition;
- }
- }
- package com.shiro.controller;
-
- import org.apache.shiro.SecurityUtils;
- import org.apache.shiro.authc.AuthenticationException;
- import org.apache.shiro.authc.AuthenticationToken;
- 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;
-
- @Controller
- @RequestMapping("myController")
- public class MyController {
- //跳转登录页面
- @GetMapping("login")
- public String login() {
- return "login";
- }
-
- @GetMapping("userLogin")
- // @ResponseBody //表达传递数据的意思
- public String userLogin(String name, String pwd,@RequestParam(defaultValue = "false")boolean rememberMe, HttpSession session) {
- //1.获取subject对象
- Subject subject = SecurityUtils.getSubject();
- //2.封装请求数据到token
- AuthenticationToken token = new UsernamePasswordToken(name, pwd, rememberMe);
- //3.调用login方法进行登录认证
- try {
- subject.login(token);
- // return "登录成功";
- session.setAttribute("user", token.getPrincipal().toString());
- return "main";
- } catch (AuthenticationException e) {
- e.printStackTrace();
- System.out.println("登录失败");
- return "登录失败";
- }
- }
-
- //登录认证验证 rememberMe
- @GetMapping("userLoginRm")
- public String userLogin(HttpSession session) {
- session.setAttribute("user", "rememberMe");
- return "main";
- }
- }
- <!DOCTYPE html>
- <html lang="en" xmlns:th="http://www.thymeleaf.org">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <h1>Shiro登录认证后主页面</h1>
- <br>
- 登录用户为:<span th:text="${session.user}"></span>
- <br>
- <a href="/logout">登出</a>
- </body>
- </html>
9.编写简单的前端页面进行测试,登录页面Login.html以及main.html - <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <h1>Shiro登录认证</h1>
- <form action="/myController/userLogin">
- <div> 用户名:<input type="text" name="name" value=""></div>
- <div>密码:<input type="password" name="pwd" value=""></div>
- <div>记住用户:<input type="checkbox" name="rememberMe" value="true"></div>
- <div><input type="submit" value="登录"></div>
- </form>
- </body>
- </html>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。