springboot系列(十)springboot整合shiro实现登录认证
关于shiro的概念和知识本篇不做详细介绍,但是shiro的概念还是需要做做功课的要不无法理解它的运作原理就无法理解使用shiro;
本篇主要讲解如何使用shiro实现登录认证,下篇讲解使用shiro实现权限控制
要实现shiro和springboot的整合需要以下几大步骤:
- 生成用户表
- 引入shiro依赖
- 添加shiro配置文件
- 添加自定义的realm
- 登录操作触发验证
- 细节处理
下面我们一步步的详细介绍:
一、生成用户表
CREATE TABLE `sys_user` (`user_id` bigint(20) NOT NULL AUTO_INCREMENT,`username` varchar(50) NOT NULL COMMENT '用户名',`password` varchar(100) DEFAULT NULL COMMENT '密码',`salt` varchar(20) DEFAULT NULL COMMENT '盐',`email` varchar(100) DEFAULT NULL COMMENT '邮箱',`mobile` varchar(100) DEFAULT NULL COMMENT '手机号',`status` tinyint(4) DEFAULT NULL COMMENT '状态 0:禁用 1:正常',`dept_id` bigint(20) DEFAULT NULL COMMENT '部门ID',`create_time` datetime DEFAULT NULL COMMENT '创建时间',PRIMARY KEY (`user_id`),UNIQUE KEY `username` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='系统用户';
二、引入shiro依赖
<!-- Apache shiro依赖 只需要引入本依赖 shiro-spring 会自动引入shiro-web和shiro-core依赖--> <dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.3.2</version> </dependency>
三、添加shiro的配置文件(本篇使用的是@Configuration注解java类的方式,也可以使用xml的方式)
package com.chuhouqi.demo.shiro;import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;@Configuration
public class ShiroConfig {@Bean("sessionManager")public SessionManager sessionManager(){DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();sessionManager.setSessionValidationSchedulerEnabled(true);sessionManager.setSessionIdUrlRewritingEnabled(false);//sessionManager.setSessionIdCookieEnabled(false);return sessionManager;}@Bean("securityManager")public SecurityManager securityManager(UserRealm userRealm, SessionManager sessionManager) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(userRealm);securityManager.setSessionManager(sessionManager);return securityManager;}@Bean("shiroFilter")public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();shiroFilter.setSecurityManager(securityManager);shiroFilter.setLoginUrl("/login");shiroFilter.setSuccessUrl("/index");shiroFilter.setUnauthorizedUrl("/403");Map<String, String> filterMap = new LinkedHashMap<>();filterMap.put("/druid/**", "anon");filterMap.put("/api/**", "anon");filterMap.put("/login", "anon");filterMap.put("/registe", "anon");filterMap.put("/registe.html", "anon");filterMap.put("/**/*.css", "anon");filterMap.put("/**/*.js", "anon");// filterMap.put("/login.html", "anon");filterMap.put("/fonts/**", "anon");filterMap.put("/plugins/**", "anon");filterMap.put("/swagger/**", "anon");filterMap.put("/favicon.ico", "anon");filterMap.put("/captcha.jpg", "anon");filterMap.put("/", "anon");filterMap.put("/**", "authc");shiroFilter.setFilterChainDefinitionMap(filterMap);return shiroFilter;}@Bean("lifecycleBeanPostProcessor")public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {return new LifecycleBeanPostProcessor();}@Beanpublic DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();proxyCreator.setProxyTargetClass(true);return proxyCreator;}@Beanpublic AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();advisor.setSecurityManager(securityManager);return advisor;}}
四、添加自定义的realm(实现认证和授权)
package com.chuhouqi.demo.shiro;import com.chuhouqi.demo.common.utils.ShiroUtil; import com.chuhouqi.demo.entity.User; import com.chuhouqi.demo.service.IUserService; import org.apache.shiro.authc.*; import org.apache.shiro.authc.credential.CredentialsMatcher; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; 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 UserRealm extends AuthorizingRealm {@Autowiredprivate IUserService userService;@Override/*** 权限授权*/protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;}@Override/*** 登录认证*/protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//获取用户输入的用户名String username = (String) token.getPrincipal();//根据用户名查询用户信息User user = userService.getUser(username);// 账号不存在if (user == null) {throw new UnknownAccountException("账号不存在");}// 账号锁定if (user.getStatus() == 0) {throw new LockedAccountException("账号已被锁定,请联系管理员");}SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),ByteSource.Util.bytes(user.getSalt()),getName());return info;}/*** 设置密码比较器为HashedCredentialsMatcher* @param credentialsMatcher*/@Overridepublic void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {HashedCredentialsMatcher shaCredentialsMatcher = new HashedCredentialsMatcher();shaCredentialsMatcher.setHashAlgorithmName(ShiroUtil.hashAlgorithmName);shaCredentialsMatcher.setHashIterations(ShiroUtil.hashIterations);super.setCredentialsMatcher(shaCredentialsMatcher);}}
五、登录操作触发验证
package com.chuhouqi.demo.controller;import com.chuhouqi.demo.common.utils.ShiroUtil; import com.chuhouqi.demo.entity.User; import com.chuhouqi.demo.service.IUserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.subject.Subject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping;@Controller public class LoginController {private static Logger logger = LoggerFactory.getLogger(LoginController.class);@Autowiredprivate IUserService userService;@GetMapping("/login")String login() {return "login";}@RequestMapping("/login")public String login(String username, String password, Model model){try {Subject subject = SecurityUtils.getSubject();UsernamePasswordToken token = new UsernamePasswordToken(username, password);subject.login(token);}catch (UnknownAccountException e) {logger.error(e.getMessage());model.addAttribute("msg",e.getMessage());return "login";}catch (IncorrectCredentialsException e) {logger.error(e.getMessage());model.addAttribute("msg","账号或密码不正确");return "login";}catch (LockedAccountException e) {logger.error(e.getMessage());model.addAttribute("msg","账号已被锁定,请联系管理员");return "login";}catch (AuthenticationException e) {logger.error(e.getMessage());model.addAttribute("msg","账户验证失败");return "login";}return "index";}@RequestMapping("/registe")public String registe(User user){userService.saveUser(user);return "ok";}@RequestMapping("/logout")public String logout(){ShiroUtil.logout();return "redirect:/login";}}
验证:
启动项目,然后随便请求一个路径都会被shiro配置的filter拦截器进行拦截,如果请求的路径需要权限认证就会进入shiro的认证管理中,如果当前用户没有登录就会调整到登录页面;
六、细节处理:
上面的介绍只是给出了一个大概的流程,其中有很多细节还是要特比注意的要不会导致认证失败,下面我们看一下有哪些细节需要处理
1、用户密码加密处理
在数据库中存储的用户密码不应该是123456这样的密码明文,被不法分子看到是很危险的,所以数据库中的密码应该是对密码进行加密后的密文,而且还要求这个加密算法是不可逆的,即由加密后的字符串不能反推回来原来的密码,如果能反推回来那这个加密是没有意义的。
现在常用的加密算法有: MD5,SHA1
而且shiro提供了SimpleHash这个加密工具来实现密码加密:
public final static String hashAlgorithmName = "SHA-256";//加密算法public final static int hashIterations = 16;//hash加密次数 public static String encrypt(String pwd,String salt){ String newPassword = new SimpleHash(hashAlgorithmName,pwd,salt,hashIterations).toHex(); return newPassword;}
如果两个人的密码一样,即存在数据表里中的两个加密后的字符串一样,然而我们希望即使两个人的密码一样,加密后的两个字符串也不一样。即需要用到MD5盐值加密。
盐值需要唯一: 一般使用随机字符串或 user id
这里提供一个工具:
String salt = RandomStringUtils.randomAlphanumeric(20);//使用随机数函数生成salt
2、配置shiro的密码比较器
上面我们用加密算法实现了密码的明文加密,现在数据库中存储的是密码密文,用户登录时使用的密码原文,如果不告诉shiro我们的密码加密算法逻辑,shiro是使用默认的比较器
进行的简单的密码比较(即使用数据库中的密码密文和用户登录时输入的密码明文进行比较),显而易见这样比较是不会成功的所以我们要告诉shiro 我们是使用的加密算法,
实现过程很简单:在我们自定义的UserRealm中添加如下配置
/*** 设置密码比较器为HashedCredentialsMatcher* @param credentialsMatcher*/@Overridepublic void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {HashedCredentialsMatcher shaCredentialsMatcher = new HashedCredentialsMatcher();shaCredentialsMatcher.setHashAlgorithmName(ShiroUtil.hashAlgorithmName);//这里就是我们进行密码加密的算法shaCredentialsMatcher.setHashIterations(ShiroUtil.hashIterations);//加密循环次数super.setCredentialsMatcher(shaCredentialsMatcher);}
转载于:https://www.cnblogs.com/keepruning/p/9305596.html
springboot系列(十)springboot整合shiro实现登录认证相关推荐
- SpringBoot整合Shiro实现登录认证和授权CHCache
文章目录 一. springboot实现普通登录 1 添加依赖 2 编写配置文件 3 新建实体类和mapper 4 编写业务层代码 5 编写控制器 6 编写启动类 7 编写登录页面和主页面 二. sp ...
- SpringBoot整合Shiro实现登录认证授权操作
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理.使用Shiro的易于理解的API,您可以快速.轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和 ...
- 《SpringBoot系列十六》条件装配时ConfigurationCondition和Condition有什么区别?什么时候用ConfigurationCondition?
一.前言 针对条件装配我们讨论了如下内容: <SpringBoot系列十一>:精讲如何使用@Conditional系列注解做条件装配 <SpringBoot系列十二>:如何自定 ...
- shiro+jwt登录认证anon配置无效
shiro+jwt登录认证anon配置无效 需求:使用shiro+jwt进行登录认证,希望可以自定义一些不需要认证的接口(登录接口等),其他统统交给jwtFilter进行token认证 原来shiro ...
- SpringBoot整合Shiro搭建登录注册认证授权权限项目模板
主要内容: 1 SpringBoot整合Shiro安全框架; 2 Shiro主要学习内容总结;(执行流程.主要对象接口.注意事项等) 3 Redis实现对权限信息缓存; ! 温馨提示: 想要快速搭Sh ...
- SpringBoot学习:整合shiro(身份认证和权限认证),使用EhCache缓存
一.在pom中引入依赖jar包 1 <properties> 2 <shiro.version>1.3.2</shiro.version> 3 </prope ...
- Springboot + Spring Security 实现前后端分离登录认证及权限控制
Spring Security简介 Spring Security 是 Spring 家族中的一个安全管理框架,实际上,在 Spring Boot 出现之前,Spring Security 就已经发展 ...
- 手把手带你在集成SpringSecurity的SpringBoot应用中添加短信验证码登录认证功能
本文目录 前言 1 自定义AuthenticationToken类 2 自定义AuthenticationProvider类 3 自定义MobilePhoneAuthenticationFilter ...
- SSM整合Shiro进行登陆认证和授权详细配置
本篇博客将进行详细介绍Shiro+Spring+SpringMVC+Mybatis+数据库整合并进行登陆认证和授权详细配置. SSM的整合可以参考:https://blog.csdn.net/a745 ...
最新文章
- [原]three.js 地形纹理混合
- Meta AI推出“杂食者”:一个模型搞定图像、视频和3D数据三大分类任务,性能还不输独立模型...
- stm32启动文件ld md hd cl vl xl分析及选择
- REUSE_ALV_GRID_DISPLAY事件子过程和cl_gui_grid类的事件对应关系
- 【FBA】SharePoint 2013自定义Providers在基于表单的身份验证(Forms-Based-Authentication)中的应用...
- Java笔记-解决读取文件时中文乱码问题(InputStreamReader设置编码)
- 判断给定数组是否包含132模式 132 Pattern
- 一位网友在某职业论坛上就发了一个相关的帖子
- XSSFWorkbook 设置单元格样式_openpyxl3.0官方文档(25)—— 使用样式
- 得到常用汉字的拼音首字母
- 文氏图Java逻辑表达式,离散数学及其应用 PDF 完整第7版
- JAVA最强工具类之一HuTool
- RabbitMQ问题解决:TCP connection succeeded but Erlang distribution failed
- 中国计算机展望未来,作文:展望未来中国的2025
- RS/CQI/SINR/RSRP/RSSI都是什么意思?
- python中常用于输出信息的语句函数是print括号_第十四课我们研究一下常用的print()函数,翻看了一下Python宝典...
- 【Python】最全中文停用词表整理(1893个)()
- 问题--联通研究院面试
- 各种软件的视频教程 链接http://www.51zxw.net/default.aspx
- 1500_什么是鱼骨图以及鱼骨图如何使用
热门文章
- php从内存中获取源码_PHP源码分析之变量的存储过程分解
- php无嵌套遍历多维数组,不递归怎么遍历多维数组(维数不定)
- html浏览器边框颜色,CSS设置字体和边框颜色时Chrome和其他主流浏览器差别的问题_html/css_WEB-ITnose...
- 深拷贝的缺点_拷贝?还傻傻分不清深浅?
- python增删改查csv文件_Python增删改查文件
- java setpaintmode 用法_详解Paint的各种set方法
- vue怎么vw布局好用_vue cli3项目的pc自适应布局_vw
- php 多数据库联合查询,php如何同时连接多个数据库_PHP教程
- matlab 柯西黎曼方程,【判断题】柯西-黎曼方程成立是函数解析的必要条件.
- java实现权限_Java实现权限管理的两种方式