Shiro中的认证对象

- Subject 主体

访问系统的用户。主体可以是用户、程序等,进行认证的都称为主体。

- Principal 身份信息

是主体进行身份认证的标识,标识具有唯一性,如用户名、手机号、邮箱等,一个主体可以有多个身份,但必须有一个主身份。

- Credential 凭证信息

是只有主体自己知道的安全信息,如密码、证书等。

Shiro的认证过程

首先主体需要携带身份信息和凭证信息,比如用户名和密码,然后Shiro会将这些信息包装成一个令牌,也就是Token,然后再通过Shiro中的安全管理器进行认证。安全管理器再调用认证器,认证器再去调用Realm获取数据。将携带的身份信息和凭证信息与原始数据进行比对,如果一致的话就会进入应用也就是登录认证成功。

Shiro配置(重点)

引入Shiro依赖

<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.4.1</version></dependency>

配置ShiroConfig

package boc.ljh.config;import boc.ljh.config.shiro.realm.UserRealm;
import boc.ljh.pojo.User;
import org.apache.logging.log4j.message.StringFormattedMessage;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.HashMap;
import java.util.Map;@Configuration
public class ShiroConfig {//1.创建ShiroFilter 负责拦截所有请求@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();//给ShiroFilter设置安全管理器shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);//配置系统受限和认证资源Map<String,String> map = new HashMap<String,String>();map.put("/user/addUser","authc");//authc 请求这个资源需要认证和授权map.put("/user/loadAllUserList","authc");shiroFilterFactoryBean.setFilterChainDefinitionMap(map);//配置认证界面  当需要进行认证时会跳到下面的login.jsp页面。shiroFilterFactoryBean.setLoginUrl("/WEB_INF/jsp/login.jsp");return shiroFilterFactoryBean;}//2.创建安全管理器@Beanpublic DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm){DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();//给安全管理器设置RealmdefaultWebSecurityManager.setRealm(realm);return defaultWebSecurityManager;}//3.创建Realm@Beanpublic Realm getRealm(){UserRealm userRealm = new UserRealm();//修改凭证匹配器HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();//设置加密算法为MD5hashedCredentialsMatcher.setHashAlgorithmName("MD5");//设置散列次数hashedCredentialsMatcher.setHashIterations(1024);userRealm.setCredentialsMatcher(hashedCredentialsMatcher);return userRealm;}
}

创建自定义的Realm

package boc.ljh.config.shiro.realm;import boc.ljh.pojo.User;
import boc.ljh.service.UserService;
import boc.ljh.utils.ApplicationContextUtils;
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.util.ObjectUtils;//自动以Realm
public class UserRealm  extends AuthorizingRealm {@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {return null;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {//根据身份信息String principal = (String) authenticationToken.getPrincipal();//在工厂中获取bean对象UserService userService = (UserService) ApplicationContextUtils.getBean("userServiceImpl");User user = userService.loadUserInfoByUsername(principal);if(!ObjectUtils.isEmpty(user)){return new SimpleAuthenticationInfo(user.getUserName(),user.getUserPassword(), ByteSource.Util.bytes(user.getUserSalt()),this.getName());}return null;}
}

生成随机盐配置

package boc.ljh.utils;import java.util.Random;public class SaltUtils {//生成随机盐public static String getSalt(int num){char[] chars = "0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz!@#$%^&*()_+-={}[],./;:\"'\\".toCharArray();StringBuilder stringBuilder = new StringBuilder();for (int i = 0; i <num ; i++){char aChar  = chars[new Random().nextInt(chars.length)];stringBuilder.append(aChar);}return stringBuilder.toString();}
}

获取工厂中bean的配置

package boc.ljh.utils;import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;/*** 配置获取工厂中bean对象*/
@Component
public class ApplicationContextUtils implements ApplicationContextAware {private static ApplicationContext context;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.context = applicationContext;}//根据bean名字获取工厂中指定的bean对象public static Object getBean(String beanName){return context.getBean(beanName);}
}

实现用户注册功能(注册时对密码进行MD5+salt+hash散列加密)

controller

package boc.ljh.controller;import boc.ljh.config.AppCode;
import boc.ljh.config.PaginationHelper;
import boc.ljh.config.Result;
import boc.ljh.pojo.User;
import boc.ljh.service.UserService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.*;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import javax.jws.soap.SOAPBinding;@Api(tags = "用户管理")
@RestController
@RequestMapping("/user")
public class UserController {@Resourceprivate UserService userService;@ApiOperation("用户注册")@PostMapping("/register")@ApiOperationSupport(ignoreParameters = {"userId","userAge","userSalt"})public Result register(@RequestBody User user){Result result = new Result();Integer num = userService.registerUserInfo(user);if(num == 1){result.setMessage("注册成功");result.setStatus(200);}else{result.setMessage("注册失败");result.setStatus(500);}return result;}}

dao

//用户注册Integer registerUserInfo(User user);

mapper.xml

<insert id="registerUserInfo" parameterType="boc.ljh.pojo.User">insert into user(user_name, user_password,user_salt) values (#{userName},#{userPassword},#{userSalt});</insert>

service

//用户注册Integer registerUserInfo(User user);

serviceImpl

@Overridepublic Integer registerUserInfo(User user) {//1.生成随机盐String salt = SaltUtils.getSalt(8);//2.将随机盐保存到数据库user.setUserSalt(salt);//明文密码进行MD5+随机盐+hash散列处理Md5Hash md5Hash = new Md5Hash(user.getUserPassword(),salt,1024);user.setUserPassword(md5Hash.toHex());Integer num = userDao.registerUserInfo(user);return num;}

实现用户登录功能

controller

@ApiOperation("用户登录")@PostMapping("/login")@ApiOperationSupport(ignoreParameters = {"userAge","userId","userSalt"})public Result login(@RequestBody User user){Result result = new Result();Subject subject = SecurityUtils.getSubject();try {subject.login(new UsernamePasswordToken(user.getUserName(),user.getUserPassword()));result.setMessage(AppCode.LOGIN_SUCCESS.message);result.setStatus(AppCode.LOGIN_SUCCESS.code);return result;}catch (UnsupportedOperationException e) {result.setMessage(AppCode.LOGIN_NAME_FALL.message);result.setStatus(AppCode.LOGIN_NAME_FALL.code);return result;}catch (IncorrectCredentialsException e){result.setMessage(AppCode.LOGIN_PASS_FALL.message);result.setStatus(AppCode.LOGIN_PASS_FALL.code);return result;}}

dao

//根据用户名获取用户信息User loadUserInfoByUsername(String usename);

mapper.xml

    <select id="loadUserInfoByUsername" resultMap="BaseResultMap">

service

//根据用户名获取用户信息User loadUserInfoByUsername(String usename);

serviceImpl

@Overridepublic User loadUserInfoByUsername(String usename) {return userDao.loadUserInfoByUsername(usename);}

实现用户退出功能

controller

@ApiOperation("用户退出")@PostMapping("/loginout")public Result loginout(){Result result = new Result();Subject subject = SecurityUtils.getSubject();subject.logout();result.setStatus(200);result.setMessage("退出成功");return result;}

springboot集成shiro实现注册、登录、退出功能相关推荐

  1. 个人博客四|注册登录退出功能后台开发

    声明:本博客的注册登录退出功能将使用django-allauth,参考资源如下: django-allauth文档 django-allauth教程 1.安装django-allauth pip in ...

  2. springboot集成shiro实现用户登录认证

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

  3. SpringBoot集成Shiro安全框架

    SpringBoot集成Shiro安全框架 1.shiro的定义 2.SpringBoot集成shiro的步骤 3.完成的效果 1.shiro的定义 1.shiro的作用 认证.授权.加密.会话管理. ...

  4. springboot集成shiro 前后端分离 统一处理shiro异常

    springboot集成shiro 前后端分离 统一处理shiro异常 参考文章: (1)springboot集成shiro 前后端分离 统一处理shiro异常 (2)https://www.cnbl ...

  5. springboot+uniapp实现简单注册登录

    springboot+uniapp实现简单注册登录 前言 后端 新建springboot项目 配置数据库 建表,写对应类 写接口,写对应xml文件 封装返回信息,封装UUID Service层 Con ...

  6. Qt开发登录/退出功能

    简要说明 本文主要介绍登录/退出的基本思路以及简单的代码实现,不涉及数据库相关操作 1.基本思路 使用Qt信号与槽的方式实现, 点击login界面下的登录按钮,发送try_login()信号,触发ma ...

  7. vue +Element-UI 实现完整的登录退出功能

    接着上篇文章开始记录,上篇最后问题已经解决,忘记了 : 导致的.已修改完成.截至目前为止,登录退出功能已实现,以下是我的代码: Login.vue <template><div cl ...

  8. 前端开发Vue项目实战:电商后台管理系统(二)-- 登录退出功能 --主页界面

    目录 1. 登录/退出功能 1.1 登录概述 1.2 token 原理分析 1.3 登录功能实现 1.3.1 Git 创建分支 1.3.2 渲染Login组件并实现路由重定向 1.3.3 设置背景颜色 ...

  9. apache shiro jar包_只需要6个步骤,springboot集成shiro,并完成登录

    小Hub领读: 导入jar包,配置yml参数,编写ShiroConfig定义DefaultWebSecurityManager,重写Realm,编写controller,编写页面,一气呵成.搞定,是个 ...

最新文章

  1. 导入旧版本Android项目时的“Unable to resolve target ‘android
  2. java工单自动化流程控件,一种工单审批的自动化处理方法及系统与流程
  3. python数据储存_五种使用python储存数据的方式
  4. 你看我还有机会吗?这么GAN让我秃然荒了!
  5. BSP UI Workbench double click component and see view list
  6. 某计算机公司的库存管理,《管理系统中计算机应用》应用题数据流程图汇总题及参考答案...
  7. 转:PostgreSQL角色、用户、权限和数据库安全
  8. Ubuntu c++调用python脚本(Anaconda)
  9. 隔壁桌的美女同事问我,凭啥子Nginx的并发数可以达到3w?我这次被打脸了~
  10. 基于深度学习的视觉 SLAM 综述
  11. 网页设计中常用的Web安全字体
  12. 2020年华为鲲鹏产业体系研究深度报告
  13. 电容器的 ESR 参数
  14. STM32F401RE Nucleo 在 keil MDK上的使用
  15. 为防止办公用计算机上的数据,2019年9月计算机一级Ms Office提分练习题(总)
  16. 深度剖析WiFi的SSID问题
  17. 教你用直播大师在局域网内发布组播节目
  18. 目前计算机无法显示的四叠字,四叠字列表(共19个),还能用的四叠字大全,带拼音,部分注释!...
  19. vb程序设计教程第4版龚沛曾 实验答案解析
  20. 左倾红黑树——左倾2-3树(不是jdk1.8的TreeMap的红黑树)

热门文章

  1. 教育硬件告别“不温不火”:有道首战告捷,教育、科技巨头虎视眈眈
  2. “智能经济”浪潮下,百度为何强调“人格化”与“服务化”?
  3. 三个球数求最大值c语言,C语言中一个简单的球3个数最大数的程序中,最后一步:printf(apos;apos;max=%d\napos;apos;,max);怎么理解...
  4. pythonpostapi_python post接口测试第一个用例日记
  5. java 抛出异常 返回值_java通过抛异常来返回提示信息
  6. 字符串缓冲区太小怎么解决_epoll的两种模式 ET和LT printf的缓冲区问题 边缘非阻塞模式...
  7. SQL语言之DQL语言学习(三)排序查询
  8. Python字符串练习题
  9. Python两个内置函数locals 和globals
  10. python实现可以被with上下文管理的类或函数