gitee地址:shiro初体验https://gitee.com/qiangning/shiro-learning.git
Apache Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理功能,可为任何应用提供安全保障 - 从命令行应用、移动应用到大型网络及企业应用。
Shiro为解决下列问题(我喜欢称它们为应用安全的四要素)提供了保护应用的API:
认证 - 用户身份识别,常被称为用户“登录”;
授权 - 访问控制;
密码加密 - 保护或隐藏数据防止被偷窥;
会话管理 - 每用户相关的时间敏感的状态。
Shiro还支持一些辅助特性,如Web应用安全、单元测试和多线程,它们的存在强化了上面提到的四个要素
2.Shiro核心组件
2.1 Subject(主体):外部应用的交互,记录当前操作用户,Subject是通过SecurityManager安全管理器进行授权的;
2.2 SecurityManager(核心安全管理器):对全部Subject进行安全管理,他是核心,SecurityManager通过Authenticato进行认证,通过Authorize授权,通过SessionManager进行会话管理;
Java
SecurityManager是一个接口继承了Authenticato,Authorize,SessionManage这三个接口
2.3 Authenticator(认证器):对用户认证,它是一个接口,shiro提供了ModularRealmAuthenticator实现类,通过实现类可以满足基本要求,也可以自定义认证器;
2.4 Authorizer(授权器):用户通过认证器来判断用户是否有此功能操作权限;
2.5 Realm(领域) :相当于数据源,SecuityManager进行认证通过Realm来获取用户权限数据;(从数据库取数据)
2.6 SessionManager(会话管理) :shiro自定义了一套会话管理,他不依赖web的session,此特性可以使它实现单点登录;
2.7 SessionDAO(会话DAO) :是对session会话的操作,比如将session存储到数据库中,可通过jdbc存储到数据库;
2.8 CacheManager(缓存管理) :用户权限数据存储在缓存,提高性能;
2.9 Cryptography(密码管理) shiro提供的一套密码加密解密组件,方便开发;
3.1 Subject : 主体 ::进行认证的都叫主体
3.2 Principal :身份信息::必须要有唯一性,一个主体能有多个身份,但是必须有一个主身份
3.3 Credential :凭证信息::只有主体知道的安全信息
Java
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.5.3</version> </dependency> 配置文件为 .ini后缀;单击测试shiro不用操作数据库;
认证代码:
Java
public class HaoAuthenticator { public static void main(String[] args) { //1.创建安全管理器对象 DefaultSecurityManager securityManager = new DefaultSecurityManager(); //2.安全管理器设置realm securityManager.setRealm(new IniRealm("classpath:shiro.ini")); //3.SecurityUtils 全局安全工具类设置安全管理器 SecurityUtils.setSecurityManager(securityManager); //4.关键对象 subject 主体 Subject subject = SecurityUtils.getSubject(); //5.创建令牌 UsernamePasswordToken token = new UsernamePasswordToken("admin","root"); try{ System.out.println("认证状态: "+ subject.isAuthenticated()); subject.login(token);//用户认证 System.out.println("认证状态: "+ subject.isAuthenticated()); }catch (UnknownAccountException e){ e.printStackTrace(); System.out.println("认证失败: 用户名不存在~"); }catch (IncorrectCredentialsException e){ e.printStackTrace(); System.out.println("认证失败: 密码错误~"); } } }
4.Realm自定义
SimpleAccountRealm主要认证和授权源码:
Java
public class SimpleAccountRealm extends AuthorizingRealm { //认证 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken upToken = (UsernamePasswordToken) token; SimpleAccount account = getUser(upToken.getUsername()); if (account != null) { if (account.isLocked()) { throw new LockedAccountException("Account [" + account + "] is locked."); } if (account.isCredentialsExpired()) { String msg = "The credentials for account [" + account + "] are expired"; throw new ExpiredCredentialsException(msg); } } return account; } //授权 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = getUsername(principals); USERS_LOCK.readLock().lock(); try { return this.users.get(username); } finally { USERS_LOCK.readLock().unlock(); } } }
自定义Realm:继承 AuthorizingRealm重写认证和授权
Java
public class CustomerRealm extends AuthorizingRealm { //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.out.println("===授权方法======="); return null; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //在token中获取用户名 String principal = (String) token.getPrincipal(); System.out.println(principal); //根据身份信息使用jdbc mybatis查询数据库 if("admin".equals(principal)){ //参数1:返回数据库中正确的用户名 //参数2:返回数据库中正确密码 //参数3:提供当前realm的名字 this.getName(); SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal,"root",this.getName()); return simpleAuthenticationInfo; } return null; } }
测试自定义Realm
Java
public class HaoCustomerRealmAuthenticator { public static void main(String[] args) { //创建securityManager DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); //设置自定义realm defaultSecurityManager.setRealm(new CustomerRealm()); //将安全工具类设置安全工具类 SecurityUtils.setSecurityManager(defaultSecurityManager); //通过安全工具类获取subject Subject subject = SecurityUtils.getSubject(); //创建token UsernamePasswordToken token = new UsernamePasswordToken("admin", "root"); try { subject.login(token); System.out.println(subject.isAuthenticated()); } catch (UnknownAccountException e) { e.printStackTrace(); System.out.println("用户名错误"); } catch (IncorrectCredentialsException e) { e.printStackTrace(); System.out.println("密码错误"); } //认证用户进行授权 if(subject.isAuthenticated()){ //1.基于角色权限控制 System.out.println(subject.hasRole("root")); } } }
使用加密来验证:md5+Salt(”盐“)代码:
Java
public class HaoShiroMD5 { public static void main(String[] args) { //使用MD5加密 Md5Hash md5Hash = new Md5Hash("admin"); System.out.println(md5Hash.toHex()); //使用MD5 + Salt处理 Md5Hash md5Hash1 = new Md5Hash("admin", "X0*7ps"); System.out.println(md5Hash1.toHex()); //使用MD5 + Salt + Hash散列 Md5Hash md5Hash2 = new Md5Hash("admin", "X0*7ps", 1024); System.out.println(md5Hash2.toHex()); } }
使用自定义Realm+MD5+Salt代码
Java
public class CustomerMd5Realm extends AuthorizingRealm { //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String primaryPrincipal = (String) principals.getPrimaryPrincipal(); System.out.println("身份信息: "+primaryPrincipal); //根据身份信息 用户名 获取当前用户的角色信息 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); return simpleAuthorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //获取身份信息 String principal = (String) token.getPrincipal(); //根据用户名查询数据库 if ("admin".equals(principal)) { //参数1: 数据库用户名 参数2:数据库md5+salt之后的密码 参数3:注册时的随机盐 参数4:realm的名字 return new SimpleAuthenticationInfo(principal, "e4f9bf3e0c58f045e62c23c533fcf633", ByteSource.Util.bytes("X0*7ps"), this.getName()); } return null; } }
测试:
Java
public class HaoCustomerMd5RealmAuthenicator { public static void main(String[] args) { //创建安全管理器 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); //注入realm CustomerMd5Realm realm = new CustomerMd5Realm(); //设置realm使用hash凭证匹配器 HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); //使用算法 credentialsMatcher.setHashAlgorithmName("md5"); //散列次数 credentialsMatcher.setHashIterations(1024); realm.setCredentialsMatcher(credentialsMatcher); defaultSecurityManager.setRealm(realm); //将安全管理器注入安全工具 SecurityUtils.setSecurityManager(defaultSecurityManager); //通过安全工具类获取subject Subject subject = SecurityUtils.getSubject(); //认证 UsernamePasswordToken token = new UsernamePasswordToken("admin", "root"); try { subject.login(token); System.out.println("登录成功"); } catch (UnknownAccountException e) { e.printStackTrace(); System.out.println("用户名错误"); }catch (IncorrectCredentialsException e){ e.printStackTrace(); System.out.println("密码错误"); } } }
访问控制,就是能访问那些东西网页资源,
授权可简 单理解为who对what(which)进行How操作:
Who,即主体(Subject),主体需要访问系统中的资源。
What,即资源(Resource),如系统菜单、页面、按钮、类方法、
系统商品信息等。资源包括_资源类型和资源实例_,比如商品信息
How,权限/许可(Permission),规定了主体对资源的操作许可,
授权方式
基于角色访问
Java
if(subject.hasRore('admin')){ //操作什么资源 }
基于资源访问
Java
if(subject.isPermission("user:update:01")){ //资源实例 //对01用户进行修改 } if(subject.isPermission("user:update:*")){ //资源类型 //对01用户进行修改 }
权限字符串: *资源标识符:操作:资源实例标识符;
eg:
用户创建权钱:user:create,或user:create:
用户修改实例:user:update:001
用户实例所有权限:user:*:001
shiro授权实现方式:
编程式:
Java
Subject subject = SecurityUtils.getSubject(); if(subject.hasRole(“admin”)) { //有权限 } else { //无权限 }
注解式:
Java
@RequiresRoles("admin") public void hello() { //有权限 }
标签式:
Java
JSP/GSP 标签:在JSP/GSP 页面通过相应的标签完成: <shiro:hasRole name="admin"> <!— 有权限—> </shiro:hasRole> 注意: Thymeleaf 中使用shiro需要额外集成!
开发授权:
先认证再授权;
Java
package com.baizhi.realm; 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.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; /** * 使用自定义realm 加入md5 + salt +hash */ public class CustomerMd5Realm extends AuthorizingRealm { //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String primaryPrincipal = (String) principals.getPrimaryPrincipal(); System.out.println("身份信息: "+primaryPrincipal); //根据身份信息 用户名 获取当前用户的角色信息,以及权限信息 xiaochen admin user SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); //将数据库中查询角色信息赋值给权限对象 simpleAuthorizationInfo.addRole("admin"); simpleAuthorizationInfo.addRole("user"); //将数据库中查询权限信息赋值个权限对象 simpleAuthorizationInfo.addStringPermission("user:*:01"); simpleAuthorizationInfo.addStringPermission("product:create"); return simpleAuthorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //获取身份信息 String principal = (String) token.getPrincipal(); //根据用户名查询数据库 if ("Hao".equals(principal)) { //参数1: 数据库用户名 参数2:数据库md5+salt之后的密码 参数3:注册时的随机盐 参数4:realm的名字 return new SimpleAuthenticationInfo(principal, "e4f9bf3e0c58f045e62c23c533fcf633", ByteSource.Util.bytes("X0*7ps"), this.getName()); } return null; } }
测试
Java
public class HaoCustomerMd5RealmAuthenicator { public static void main(String[] args) { //创建安全管理器 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); //注入realm CustomerMd5Realm realm = new CustomerMd5Realm(); //设置realm使用hash凭证匹配器 HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); //使用算法 credentialsMatcher.setHashAlgorithmName("md5"); //散列次数 credentialsMatcher.setHashIterations(1024); realm.setCredentialsMatcher(credentialsMatcher); defaultSecurityManager.setRealm(realm); //将安全管理器注入安全工具 SecurityUtils.setSecurityManager(defaultSecurityManager); //通过安全工具类获取subject Subject subject = SecurityUtils.getSubject(); //认证 UsernamePasswordToken token = new UsernamePasswordToken("hao", "1111"); try { subject.login(token); System.out.println("登录成功"); } catch (UnknownAccountException e) { e.printStackTrace(); System.out.println("用户名错误"); }catch (IncorrectCredentialsException e){ e.printStackTrace(); System.out.println("密码错误"); } //授权 if(subject.isAuthenticated()){ //基于角色权限控制 System.out.println(subject.hasRole("super")); //基于多角色权限控制 System.out.println(subject.hasAllRoles(Arrays.asList("admin", "super"))); //是否具有其中一个角色 boolean[] booleans = subject.hasRoles(Arrays.asList("admin", "super", "user")); for (boolean aBoolean : booleans) { System.out.println(aBoolean); } System.out.println("=============================================="); //基于权限字符串的访问控制 资源标识符:操作:资源类型 System.out.println("权限:"+subject.isPermitted("user:update:01")); System.out.println("权限:"+subject.isPermitted("product:create:02")); //分别具有那些权限 boolean[] permitted = subject.isPermitted("user:*:01", "order:*:10"); for (boolean b : permitted) { System.out.println(b); } //同时具有哪些权限 boolean permittedAll = subject.isPermittedAll("user:*:01", "product:create:01"); System.out.println(permittedAll); } } }
5.整合springboot
5.1引入依赖
Java
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-starter</artifactId> <version>1.5.3</version> </dependency>
5.1.1创建配置类
常见过滤器
配置缩写
对应的过滤器
功能
anon
AnonymousFilter
指定url可以匿名访问
authc
FormAuthenticationFilter
指定url需要form表单登录,默认会从请求中获取username、password,rememberMe等参数并尝试登录,如果登录不了就会跳转到loginUrl配置的路径。我们也可以用这个过滤器做默认的登录逻辑,但是一般都是我们自己在控制器写登录逻辑的,自己写的话出错返回的信息都可以定制嘛。
authcBasic
BasicHttpAuthenticationFilter
指定url需要basic登录
logout
LogoutFilter
登出过滤器,配置指定url就可以实现退出功能,非常方便
noSessionCreation
NoSessionCreationFilter
禁止创建会话
perms
PermissionsAuthorizationFilter
需要指定权限才能访问
port
PortFilter
需要指定端口才能访问
rest
HttpMethodPermissionFilter
将http请求方法转化成相应的动词来构造一个权限字符串,这个感觉意义不大,有兴趣自己看源码的注释
roles
RolesAuthorizationFilter
需要指定角色才能访问
ssl
SslFilter
需要https请求才能访问
user
UserFilter
需要已登录或“记住我”的用户才能访问
==================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================
ShiroConfig
Java
package com.hao.shiro.config; import com.hao.shiro.shiro.realms.CustomerRealm; 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; /* *@hao * * * */ @Configuration public class ShiroConfig { //创建shiro的filter//负责拦截所有请求 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); //注入安全管理器 shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); //配置系统授限资源 //配置系统公共资源 Map<String,String> map=new HashMap<>(); map.put("/user/login.jsp","anon"); map.put("/user/register.jsp","anon"); map.put("/index.jsp","authc");//请求这个资源需要认证和授权 shiroFilterFactoryBean.setFilterChainDefinitionMap(map); //默认认证界面 shiroFilterFactoryBean.setLoginUrl("/login.jsp"); return shiroFilterFactoryBean; } //创建安全管理器 @Bean public DefaultWebSecurityManager getdefaultWebSecurityManager (Realm realm){ DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); //给安全管理器设置 defaultWebSecurityManager.setRealm(realm); return defaultWebSecurityManager; } //创建自定义realm @Bean public Realm getRealm(){ CustomerRealm customerRealm = new CustomerRealm(); //设置hashed凭证匹配器 HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); //设置md5加密 credentialsMatcher.setHashAlgorithmName("md5"); //设置散列次数 credentialsMatcher.setHashIterations(1024); customerRealm.setCredentialsMatcher(credentialsMatcher); return customerRealm; } }
UserController
Java
package com.hao.shiro.controller; import com.hao.shiro.entity.User; import com.hao.shiro.service.UserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /* *@hao * * * */ @Controller @RequestMapping("user") public class UserController { @RequestMapping("/logout") public String logout(){ Subject subject = SecurityUtils.getSubject(); subject.logout(); System.out.println("退出登录"); return "redirect:/login.jsp"; } @Autowired private UserService userService; /** * 用户注册 */ @RequestMapping("register") public String register(User user) { try { userService.register(user); return "redirect:/login.jsp"; }catch (Exception e){ e.printStackTrace(); return "redirect:/register.jsp"; } } @RequestMapping("login") public String login(String username,String password){ //获取主体对象 Subject subject= SecurityUtils.getSubject(); try { subject.login(new UsernamePasswordToken(username,password)); return "redirect:/index.jsp"; }catch (UnknownAccountException e){ e.printStackTrace(); System.out.println("用户名错误"); }catch (IncorrectCredentialsException e){ e.printStackTrace(); System.out.println("密码错误"); } return "redirect:/login.jsp"; } }
UserDAO
Java
package com.hao.shiro.dao; import com.hao.shiro.entity.User; import org.apache.ibatis.annotations.Mapper; /* *@hao * * * */ @Mapper public interface UserDAO { void save(User user); User findByUserName(String username); }
User
Java
package com.hao.shiro.entity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; /* *@hao * * * */ @Data @Accessors(chain = true) @AllArgsConstructor @NoArgsConstructor public class User { private String id; private String username; private String password; private String salt; }
UserService
Java
package com.hao.shiro.service; import com.hao.shiro.entity.User; public interface UserService { void register(User user); User findByUserName(String username); }
UserServiceImpl
Java
package com.hao.shiro.service; import com.hao.shiro.dao.UserDAO; import com.hao.shiro.entity.User; import com.hao.shiro.utils.SaltUtils; import org.apache.shiro.crypto.hash.Md5Hash; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; /* *@hao * * * */ @Service("userService") @Transactional public class UserServiceImpl implements UserService { @Autowired private UserDAO userDAO; @Override public User findByUserName(String username) { return userDAO.findByUserName(username); } @Override public void register(User user){ //处理业务 //加密 //处理业务调用dao //1.生成随机盐 String salt = SaltUtils.getSalt(8); //2.将随机盐保存到数据 user.setSalt(salt); //3.明文密码进行md5 + salt + hash散列 Md5Hash md5Hash = new Md5Hash(user.getPassword(),salt,1024); user.setPassword(md5Hash.toHex()); userDAO.save(user); } }
CustomerRealm
Java
package com.hao.shiro.shiro.realms; import com.hao.shiro.entity.User; import com.hao.shiro.service.UserService; import com.hao.shiro.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; /* *@hao * * * */ public class CustomerRealm extends AuthorizingRealm { //处理授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { return null; } //处理认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("--------进入认证--------"); //根据身份信息 String principal = (String) token.getPrincipal(); //在工厂中获取service对象 UserService userService = (UserService) ApplicationContextUtils.getBean("userService"); //根据身份信息查询 User user = userService.findByUserName(principal); if(!ObjectUtils.isEmpty(user)){ //返回数据库信息 return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(), ByteSource.Util.bytes(user.getSalt()),this.getName()); } return null; } }
ApplicationContextUtils
Java
package com.hao.shiro.utils; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; /* *@hao * * * */ @Component public class ApplicationContextUtils implements ApplicationContextAware { private static ApplicationContext context; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context=applicationContext; } public static Object getBean(String beanName){ return context.getBean(beanName); } }
SaltUtils
Java
package com.hao.shiro.utils; import java.util.Random; /* *@hao * * * */ public class SaltUtils { /** * 生成salt的静态方法 * @param n * @return */ public static String getSalt(int n){ char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890!@#$%^&*()".toCharArray(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < n; i++) { char aChar = chars[new Random().nextInt(chars.length)]; sb.append(aChar); } return sb.toString(); } }
applicattin
Java
server.port=8080 server.servlet.context-path=/shiro spring.application.name=shiro spring.mvc.view.prefix=/ spring.mvc.view.suffix=.jsp spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/shiro?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false spring.datasource.username=root spring.datasource.password=root mybatis.type-aliases-package=com.hao.shiro.entity mybatis.mapper-locations=classpath:mapper/*.xml
Mapper->UserDaoMapper.xml
Java
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.hao.shiro.dao.UserDAO"> <insert id="save" parameterType="User" useGeneratedKeys="true" keyProperty="id"> insert into t_user values(#{id},#{username},#{password},#{salt}) </insert> <select id="findByUserName" parameterType="String" resultType="User"> select id,username,password,salt from t_user where username = #{username} </select> </mapper>
webapp–>
index.jsp
Java
<%@page contentType="text/html; utf-8" pageEncoding="utf-8" isELIgnored="false" %> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>主页</title> </head> <body> <h1>系统主页</h1> <a href="${pageContext.request.contextPath}/user/logout">退出登录</a> <ol> <li><a href="">用户页面</a></li> <li><a href="">食品页面</a></li> <li><a href="">订单页面</a></li> <li><a href="">物流页面</a></li> </ol> </body> </html>
login.jsp
Java
<%@page contentType="text/html; utf-8" pageEncoding="utf-8" isELIgnored="false" %> <!<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>用户登录</title> </head> <body> <h1>用户登录</h1> <form action="${pageContext.request.contextPath}/user/login" method="get"> 用户名:<input type="text" name="username"><br> 密 码:<input type="text" name="password"> <input type="submit" value="登录"><a href="/shiro/register.jsp">立即注册</a> </form> </body> </html>
register.jsp
Java
<%@page contentType="text/html; utf-8" pageEncoding="utf-8" isELIgnored="false" %> <!<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>用户登录</title> </head> <body> <h1>用户注册</h1> <form action="${pageContext.request.contextPath}/user/register" method="get"> 用户名:<input type="text" name="username"><br> 密 码:<input type="text" name="password"> <input type="submit" value="立即注册"> </form> </body> </html>
开启自带缓存
Java
//开启自带的缓存管理 customerRealm.setCacheManager(new EhCacheManager()); customerRealm.setCachingEnabled(true);//开启全局缓存 customerRealm.setAuthenticationCachingEnabled(true);//认证认证缓存 customerRealm.setAuthenticationCacheName("authenticationCache"); customerRealm.setAuthorizationCachingEnabled(true);//开启授权缓存 customerRealm.setAuthorizationCacheName("authorizationCache"); return customerRealm;
pom主要导入依赖
Java
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-starter</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!--mybatis相关依赖--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.2</version> </dependency> <!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <!--druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.19</version> </dependency> <!--引入shiro和ehcache--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.5.3</version> </dependency> <!--redis整合springboot--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
配置文件
Java
server.port=8080 server.servlet.context-path=/shiro spring.application.name=shiro spring.mvc.view.prefix=/ spring.mvc.view.suffix=.jsp spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/shiro?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false spring.datasource.username=root spring.datasource.password=root mybatis.type-aliases-package=com.hao.shiro.entity mybatis.mapper-locations=classpath:mapper/*.xml spring.redis.port=6379 spring.redis.host=localhost spring.redis.database=0
sql
Java
/* SQLyog Professional v12.09 (64 bit) MySQL - 5.7.34-log : Database - shiro ********************************************************************* */ /*!40101 SET NAMES utf8 */; /*!40101 SET SQL_MODE=''*/; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; CREATE DATABASE /*!32312 IF NOT EXISTS*/`shiro` /*!40100 DEFAULT CHARACTER SET utf8 */; USE `shiro`; /*Table structure for table `t_perms` */ DROP TABLE IF EXISTS `t_perms`; CREATE TABLE `t_perms` ( `id` int(6) NOT NULL AUTO_INCREMENT, `name` varchar(80) DEFAULT NULL, `url` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; /*Data for the table `t_perms` */ insert into `t_perms`(`id`,`name`,`url`) values (1,'user:*:*',NULL),(2,'product:*:01',NULL),(3,'order:*:*',NULL); /*Table structure for table `t_role` */ DROP TABLE IF EXISTS `t_role`; CREATE TABLE `t_role` ( `id` int(6) NOT NULL AUTO_INCREMENT, `name` varchar(60) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; /*Data for the table `t_role` */ insert into `t_role`(`id`,`name`) values (1,'admin'),(2,'user'),(3,'product'); /*Table structure for table `t_role_perms` */ DROP TABLE IF EXISTS `t_role_perms`; CREATE TABLE `t_role_perms` ( `id` int(6) NOT NULL, `roleid` int(6) DEFAULT NULL, `permsid` int(6) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*Data for the table `t_role_perms` */ insert into `t_role_perms`(`id`,`roleid`,`permsid`) values (1,1,1),(2,1,2),(3,2,1),(4,3,2),(5,1,3); /*Table structure for table `t_user` */ DROP TABLE IF EXISTS `t_user`; CREATE TABLE `t_user` ( `id` int(6) NOT NULL AUTO_INCREMENT, `username` varchar(40) DEFAULT NULL, `password` varchar(40) DEFAULT NULL, `salt` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; /*Data for the table `t_user` */ insert into `t_user`(`id`,`username`,`password`,`salt`) values (1,'hao','567f86681241739ba8cf3d26e52eaafc','XK&7UIS^'),(2,'qiang','d750daee137e0666193a1720732fe97d','UVcob7pR'); /*Table structure for table `t_user_role` */ DROP TABLE IF EXISTS `t_user_role`; CREATE TABLE `t_user_role` ( `id` int(6) NOT NULL, `userid` int(6) DEFAULT NULL, `roleid` int(6) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*Data for the table `t_user_role` */ insert into `t_user_role`(`id`,`userid`,`roleid`) values (1,1,1),(2,2,2),(3,2,3); /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
苏公网安备 32132202001088号
| Copyright 北极熊 北格技术 版权所有