springboot系列(十)springboot整合shiro实现登录认证

关于shiro的概念和知识本篇不做详细介绍,但是shiro的概念还是需要做做功课的要不无法理解它的运作原理就无法理解使用shiro;

本篇主要讲解如何使用shiro实现登录认证,下篇讲解使用shiro实现权限控制

要实现shiro和springboot的整合需要以下几大步骤:

  1. 生成用户表
  2. 引入shiro依赖
  3. 添加shiro配置文件
  4. 添加自定义的realm
  5. 登录操作触发验证
  6. 细节处理

下面我们一步步的详细介绍:

一、生成用户表

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/538267.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

recyclerview item动画_这可能是你见过的迄今为止最简单的RecyclerView Item加载动画...

如何实现RecyclerView Item动画&#xff1f; 这个问题想必有很多人都会讲&#xff0c;我可以用ItemAnimator实现啊&#xff0c;这是RecyclerView官方定义的接口&#xff0c;专门扩展Item动画的&#xff0c;那我为什么要寻求另外一种方法实现呢&#xff1f;因为最近反思了一个问…

群晖编译LCD4Linux,LCD4LINUX配置文件一些参数使用解释。

#LCD显示配置Display dpf {Driver DPF #LCD驱动类型Port usb0 #连接端口Font 6x8 #字体大小Foreground ffffff #字体…

VBoxManage: error: Nonexistent host networking interface, name 'vboxnet0' (VERR_INTERNAL_ERROR)

错误&#xff1a; VBoxManage: error: Nonexistent host networking interface, name vboxnet0 (VERR_INTERNAL_ERROR) 原因&#xff1a; 原来配置的网卡发生了变更&#xff0c;找不到了&#xff0c;启动失败。 解决方法&#xff1a; 第一步&#xff0c;命令&#xff1a; V…

捷信达温泉管理软件员工卡SQL查询

捷信达温泉管理软件员工卡SQL查询 select * from snkey where v_name2 like %员工% 网名&#xff1a;浩秦; 邮箱&#xff1a;root#landv.pw; 只要我能控制一個國家的貨幣發行&#xff0c;我不在乎誰制定法律。金錢一旦作響&#xff0c;壞話隨之戛然而止。

Linux 软件安装到 /usr,/usr/local/ 还是 /opt 目录?

Linux 的软件安装目录是也是有讲究的&#xff0c;理解这一点&#xff0c;在对系统管理是有益的 /usr&#xff1a;系统级的目录&#xff0c;可以理解为C:/Windows/&#xff0c;/usr/lib理解为C:/Windows/System32。 /usr/local&#xff1a;用户级的程序目录&#xff0c;可以理解…

winpe装双系统linux_使用syslinux在u盘安装pubbylinux和winpe双系统

使用syslinux在u盘安装pubbylinux和winpe双系统1,在u盘里安装winpe,请参见"比较简单的制作U盘winpe启动盘方法"比较简单的制作U盘winpe启动盘方法 收藏1,下载一个深度winpev3.iso2,用winrar或ultraISO解压深度winpev3.iso3,进入解压出来的文件夹下&#xff0c;找到se…

esp32 嵌入式linux,初体验乐鑫 ESP32 AT 指令-嵌入式系统-与非网

乐鑫 AT 固件初体验初步体验 AT 指令下 TCP 数传&#xff0c;为了验证 AT 命令解析器。前往乐鑫官网 下载最新版本 AT 固件和 AT 指令集手册。硬件准备本文使用乐鑫的 ESP-WROOM-32(ESP-WROOM-32 是 ESP32-WROOM-32 的曾用名)模块&#xff0c;4MB Flash&#xff0c;无 PSRAM。E…

主机ping不通Virtualbox里的虚拟机

在redhat上安装了VirtualBox&#xff0c;虚拟了三台Linux机器。 宿主机网卡更换过了。三台虚拟机无法启动了&#xff0c;搭建虚拟机的运维离职了。 VirtualBox的图形界面坏了&#xff0c;启动不了。只能用命令行&#xff0c;今天时间就花在命令行上了。 第一个问题是&#xf…

python后端开发靠谱吗_【后端开发】python有这么强大吗

因为Python是一种代表简单主义思想的语言。除此之外&#xff0c;Python所拥有的标准库更是金融、营销类人群选择它的理由。Python 易于学习可靠且高效(推荐学习&#xff1a;Python视频教程)好吧&#xff0c;相较于其它许多你可以拿来用的编程语言而言&#xff0c;它“更容易一些…

linux 卸载 openldap,Linux下安装openldap

Ubuntu apt-getinstall安装参考&#xff1a;http://dongwang.wordpress.com/category/uncategorized/普通linux安装,以XXX用户身份安装&#xff1a;1、安装BerkeleyDB 4.7.25&#xff1a;伯克利大学嵌入式数据库解决方案,openldap拿它作为存储方案。http://download.oracle.com…

Git之原有基础开发新功能

场景描述 当一个项目已经上线&#xff0c;同时又在原有基础上新增功能模块&#xff0c;于是乎就要在原有代码的基础上进行开发&#xff0c;在新增模块功能的开发的过程中&#xff0c;项目发现了一个紧急Bug&#xff0c;需要修复。操作流程如下&#xff1a; -------------------…

pantum打印机驱动安装m6506_奔图Pantum M6506NW 驱动

这是奔图Pantum M6506NW 驱动&#xff0c;是M6506NW奔图打印机驱动&#xff0c;此设备内置WIFI热点&#xff0c;安装驱动可以帮助用户解决打印机连接和工作中出现的问题&#xff0c;非常方便&#xff0c;需要的朋友快来本站下载吧&#xff01;驱动介绍奔图M6506NW一体机驱动专为…

linux kvm查看线程状态,kvm线程-005-线程状态-THREAD_JUST_BORN

在kvm内部定义了线程状态,如下:enum {THREAD_JUST_BORN 1, /* 还没有启动*/THREAD_ACTIVE 2, /* 当前正在运行,或者在等待运行的队列中*/THREAD_SUSPENDED 4, /* 等待monitor或者alarm */THREAD_DEAD 8, /* 线程退出 */THREAD_MONITOR_WAIT 16, // 等待锁THREAD_CONVAR_WA…

详解VirtualBox虚拟机网络环境解析和搭建-NAT、桥接、Host-Only、Internal、端口映射

原文链接&#xff1a;http://www.jb51.net/article/98575.htm -------------------------------------------------- 本文以VirtualBox为例 如果出现主机无法ping通虚拟机的情况&#xff0c;请首先确认虚拟机防火墙已关闭。 一、NAT模式 特点&#xff1a; 1、如果主机可以上网…

os.popen read()报编码错误_数据科学家易犯的十大编码错误,你中招了吗?

选自 Medium作者&#xff1a;Norm Niemer机器之心编译参与&#xff1a;李诗萌、王淑婷数据科学家比软件工程师擅长统计&#xff0c;又比统计学家擅长软件工程。听起来牛逼轰轰&#xff0c;事实却是&#xff0c;许多数据科学家有统计学背景&#xff0c;却没有什么软件工程方面的…

linux怎么添加工作组,linux 用户与工作组

在linux 里面&#xff0c;用户的编号UID &#xff0c;也就是用户的ID号。工作组的编号为GID 也就是工作组的ID 号 。1、用户的分类超级用户&#xff1a;root用户&#xff0c;系统安装过程中自动创建&#xff0c;UID 为0。普通用户&#xff1a;操作权限受到限制的用户id在 500-6…

MySQL5.7.12新密码登录方式及密码策略

原文链接&#xff1a;http://www.cnblogs.com/jonsea/p/5510219.html --------------------------------------------------------------------------- 松门一枝花补充 最简单的方法&#xff1a; 1、配置文件中把密码策略关了。本文中间部分有介绍。 2、重启服务 3、用my…

聚类分析在用户行为中的实例_聚类分析案例之市场细分

聚类是将数据分类到不同的类或者簇这样的一个过程&#xff0c;所以同一个簇中的对象有很大的相似性&#xff0c;而不同簇间的对象有很大的相异性。从统计学的观点看&#xff0c;聚类分析是通过数据建模简化数据的一种方法。传统的统计聚类分析方法包括系统聚类法、分解法、加入…

linux 编译system.img,android生成sysytem.img的命令过程

Fromhttp://xianghuaclm.blog.163.com/blog/static/6668783201110221486240/使用#file system.img输出&#xff1a;system.img: Linux rev 0.0 ext2 filesystem data,UUID4eb0489c-647d-49d8-9111-94657b5fd342, volume name"system"。然而本人使用命令#mkyaffs2imag…

Hive的hiveserver2后台开启和关闭

前提&#xff1a;hive/bin配置了环境变量。如果没有配置&#xff0c;cd到 hive目录下的bin里&#xff0c;再执行。 开启命令&#xff1a; nohup hive --service hiveserver2 & 产生的日志&#xff1a; 默认在&#xff1a; 用户文件夹里 [rootmaster ~]# ll total 80 …