推荐大气的网站,兰州网站开发哪里可以做,网站建设经验典型,织梦大气蓝色门户资讯网站模板关于shiro的概念和知识本篇不做详细介绍#xff0c;但是shiro的概念还是需要做做功课的要不无法理解它的运作原理就无法理解使用shiro#xff1b; 本篇主要讲解如何使用shiro实现登录认证#xff0c;下篇讲解使用shiro实现权限控制 要实现shiro和springboot的整合需要以下几…关于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)
) ENGINEInnoDB AUTO_INCREMENT2 DEFAULT CHARSETutf8 COMMENT系统用户; 二、引入shiro依赖 !-- Apache shiro依赖 只需要引入本依赖 shiro-spring 会自动引入shiro-web和shiro-core依赖--
dependencygroupIdorg.apache.shiro/groupIdartifactIdshiro-spring/artifactIdversion1.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);MapString, 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这样的密码明文被不法分子看到是很危险的所以数据库中的密码应该是对密码进行加密后的密文而且还要求这个加密算法是不可逆的即由加密后的字符串不能反推回来原来的密码如果能反推回来那这个加密是没有意义的。 现在常用的加密算法有 MD5SHA1 而且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