shiro
快速开始
1.导入依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.8.0</version>
</dependency>
<!-- configure logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.8.0</version>
</dependency>
2.配置文件
shiro.ini
[users]
# user 'root' with password 'secret' and the 'admin' role
root = secret, admin
# user 'guest' with the password 'guest' and the 'guest' role
guest = guest, guest
# user 'presidentskroob' with password '12345' ("That's the same combination on
# my luggage!!!" ;)), and role 'president'
presidentskroob = 12345, president
# user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'
darkhelmet = ludicrousspeed, darklord, schwartz
# user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz'
lonestarr = vespa, goodguy, schwartz
# -----------------------------------------------------------------------------
# Roles with assigned permissions
#
# Each line conforms to the format defined in the
# org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc
# -----------------------------------------------------------------------------
[roles]
# 'admin' role has all permissions, indicated by the wildcard '*'
admin = *
# The 'schwartz' role can do anything (*) with any lightsaber:
schwartz = lightsaber:*
# The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with
# license plate 'eagle5' (instance specific id)
goodguy = winnebago:drive:eagle5
log4j.properties
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n
# General Apache libraries
log4j.logger.org.apache=WARN
# Spring
log4j.logger.org.springframework=WARN
# Default Shiro logging
log4j.logger.org.apache.shiro=INFO
# Disable verbose logging
log4j.logger.org.apache.shiro.util.ThreadContext=WARN
log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN
3.快速开始测试
Subject currentUser = SecurityUtils.getSubject();
Session session = currentUser.getSession();
currentUser.isAuthenticated()
currentUser.getPrincipal()
currentUser.hasRole()
currentUser.isPermitted()
currentUser.logout();
springboot集成shiro
-
整合
org.thymeleaf thymeleaf-spring5 3.0.11.RELEASE org.thymeleaf.extras thymeleaf-extras-java8time 3.0.4.RELEASEthymeleaf
-
thymeleaf
语法提示 -
设置自定义Realm,重写授权认证方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7diBD6y4-1641475033014)(/Users/heroma/Library/Application Support/typora-user-images/image-20220104191443906.png)]
package com.hero.config;
import com.hero.pojo.User;
import com.hero.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import sun.tools.jstat.Token;//自定义UserRealm,继承AuthorizingRealm
public class UserRealm extends AuthorizingRealm {
@Autowired
UserService userService;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println(“执行了授权:doGetAuthorizationInfo”);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// info.addStringPermission(“user:add”);
Subject subject = SecurityUtils.getSubject();
User currentUser = (User)subject.getPrincipal();
//设置当前用户的权限
info.addStringPermission(currentUser.getPerms());
return info ;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println(“执行了认证:doGetAuthorizationInfo”);
//用户名 密码 数据中获取
//连接数据库
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
User user = userService.queryUserByName(token.getUsername());
if (user == null){
return null; //抛出异常
}
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
session.setAttribute(“loginUser”, user);
//密码认证,shiro做
return new SimpleAuthenticationInfo(user,user.getPwd(),"");
}
} -
shiro配置类,springboot需要管理三个类
-
自定义的
UserRealm
类//创建Realm对象,需要自定义
@Bean
public UserRealm userRealm(){
return new UserRealm();
} -
DefaultWebSecurityManager
//DefaultWebSecurityManager
@Bean(name = “securityManager”)
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier(“userRealm”) UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);return securityManager; }
ShiroFilterFactoryBean
//ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier(“securityManager”) DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(securityManager);
//添加shiro过滤器
/**
* anon:无需认证就可访问
* authc:必须认证了才可访问
* user:必须y拥有 记住我 功能才能使用
* perms:拥有某个资源的权限才能访问
* role:拥有某个角色的权限才能访问
/
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// filterChainDefinitionMap.put("/user/add",“authc”);
// filterChainDefinitionMap.put("/user/update",“authc”);
//授权 正常情况下未授权会转换到未授权页面
filterChainDefinitionMap.put("/user/add",“perms[user:add]”);
filterChainDefinitionMap.put("/user/update",“perms[user:update]”);
// filterChainDefinitionMap.put("/user/",“perms[user:all]”);
filterChainDefinitionMap.put("/user/*",“authc”);
bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
bean.setLoginUrl("/toLogin");
bean.setUnauthorizedUrl("/noauth");
return bean;
} -
springboot连接数据库
-
导入相关依赖
<dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.17</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.1</version> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> <version>3.0.11.RELEASE</version> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-java8time</artifactId> <version>3.0.4.RELEASE</version> </dependency>
-
配置
application.yml
文件spring:
datasource:
username: “root”
password: “031516”
#?serverTimezone=UTC解决时区的报错
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource#Spring Boot 默认是不注入这些属性值的,需要自己绑定 #druid 数据源专有配置 initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入 #如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j filters: stat,wall,log4j maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
-
配置
mybatis
mybatis:
type-aliases-package: com.hero.pojo
mapper-locations: mapper/*.xml -
创建用户表
create table mybatis.user ( id int not null, name varchar(255) not null, pwd varchar(255) not null, perms varchar(255) null );
-
创建pojo类,跟数据库字段相同
package com.hero.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; private String pwd; private String perms; }
-
创建mapper接口
package com.hero.mapper; import com.hero.pojo.User; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @Repository @Mapper public interface UserMapper { public User queryUserByName(String name); }
-
绑定
UserMapper.xml
文件<?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.hero.mapper.UserMapper"> <select id="queryUserByName" parameterType="String" resultType="User"> select * from user where name = #{name} </select> </mapper>
-
创建
UserService
接口package com.hero.service; import com.hero.pojo.User; public interface UserService { public User queryUserByName(String name); }
-
UserService
的接口实现类UserServiceImpl
package com.hero.service; import com.hero.mapper.UserMapper; import com.hero.pojo.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserServiceImpl implements UserService { @Autowired UserMapper userMapper; @Override public User queryUserByName(String name) { return userMapper.queryUserByName(name); } }
-
编写
Mycontroller
package com.hero.controller; 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.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class Mycontroller { @RequestMapping({"/","/index"}) public String toIndex(Model model){ model.addAttribute("msg", "hello,shiro"); return "index"; } @RequestMapping("/user/add") public String toAdd(){ return "user/add"; } @RequestMapping("/user/update") public String toUpdate(){ return "user/update"; } @RequestMapping("/toLogin") public String toLogin(){ return "login"; } @RequestMapping("/login") public String login(String userName, String passWord, Model model){ //读取当前用户 Subject securityManager = SecurityUtils.getSubject(); //封装用户登录数据 UsernamePasswordToken token = new UsernamePasswordToken(userName, passWord); try { securityManager.login(token);//执行登录的方法 return "index"; }catch (UnknownAccountException e){ model.addAttribute("msg", "用户错误"); return "login"; }catch (IncorrectCredentialsException e){ model.addAttribute("msg", "密码错误"); return "login"; } } @RequestMapping("/noauth") @ResponseBody public String noAuth(){ return "未经授权"; } @RequestMapping("/logout") public String logOut(){ //读取当前用户 Subject subject = SecurityUtils.getSubject(); subject.logout(); return "index"; } }
-
主页
首页 首页
登录登出addupdate -
登录
Title 登录
用户名:
密 码:
-
添加
Title add
-
更新
Title update