SpringBoot整合Shiro
SpringBoot整合Shiro编程步骤博客
环境搭建 第一步:创建项目,添加依赖
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-thymeleaf
org.apache.shiro
shiro-spring-boot-web-starter
1.6.0
org.apache.shiro
shiro-all
1.6.0
org.slf4j
jcl-over-slf4j
1.7.30
org.slf4j
slf4j-log4j12
1.7.30
log4j
log4j
1.2.17
org.projectlombok
lombok
1.18.12
第二步:编写log4j.properties
### 设置###
log4j.rootLogger = debug,stdout,D,E
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/debug.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
第三步:自定义Realm
public class UserRealm extends AuthorizingRealm {
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("=======doGetAuthorizationInfo===============");
return null;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("=========doGetAuthenticationInfo===============");
return null;
}
}
第四步:Shiro配置文件
@Configuration
public class ShiroConfig {
//1.创建realm对象,使用自定义类
@Bean(name = "userRealm")
public UserRealm myShiroRealm() { //将自己的验证方式加入容器
UserRealm userRealm = new UserRealm();
return userRealm;
}
//2.创建DefaultWebSecurityManager
@Bean(name = "dwSecurityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
//关联realm
manager.setRealm(userRealm);
return manager;
}
//3.创建ShiroFilterFactoryBean
@Bean(name = "shiroFilterFactoryBean")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("dwSecurityManager") DefaultWebSecurityManager manager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(manager);
return bean;
}
}
第五步:按下图所示创建网页:
- add.html
DOCTYPE html>
增加用户
增加用户
- update.html
DOCTYPE html>
修改用户
修改用户
- index.html
DOCTYPE html>
首页
增加用户
修改用户
第六步:创建数据库模拟类
public class DB {
private static List users = new ArrayList();
private static Map auths = new HashMap();
static {
users.add(new User(1001, "hc", "hc"));
users.add(new User(1002, "zhangsan", "zhangsan"));
users.add(new User(1003, "lisi", "lisi"));
users.add(new User(1004, "wanger", "wanger"));
auths.put(1001, new HashSet(Arrays.asList("user:add", "user:update")));
auths.put(1002, new HashSet(Arrays.asList("user:add")));
auths.put(1003, new HashSet(Arrays.asList("user:update")));
auths.put(1004, new HashSet(Arrays.asList("user:add", "user:update")));
}
public static Set getAuths(Integer userId){
return auths.get(userId);
}
public static User getUserByUsername(String username) {
for (User user : users) {
if (user.getUsername().equals(username)) {
return user;
}
}
return null;
}
}
第七步:分发用户请求的控制器
@Controller
public class DispatchController {
@RequestMapping("/index")
public String index(Model model){
model.addAttribute("msg","Hello,Shiro");
return "index";
}
@RequestMapping("/login")
public String login(){
return "login";
}
}
第八步:分发处理用户相关请求的控制器
@Controller
@RequestMapping("/user")
@Log4j
public class UserController {
@RequestMapping("/add")
public String add(Model model) {
return "user/add";
}
@RequestMapping("/update")
public String update(Model model) {
return "user/update";
}
}
部署项目运行,在index页面中单击”增加用户”或者“修改用户”超连接,结果都会直接打开对应的页面。
Shiro实现登录拦截 第一步:修改ShiroConfig中getShiroFilterFactoryBean方法,为其添加登录拦截的代码:@Bean(name = "shiroFilterFactoryBean")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("dwSecurityManager") DefaultWebSecurityManager manager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(manager);
//添加shiro的内置过滤器
Map map = new LinkedHashMap();
//拦截
map.put("/user/add", "authc");
map.put("/user/update", "authc");
//------------②
bean.setFilterChainDefinitionMap(map);
bean.setLoginUrl("/login"); //--------①
//设置安全管理器
return bean;
}
上面编号①处的login对应的是在templates目录的login.html页面,其代码如下:
DOCTYPE html>
登录
用户名:
密码:
部署项目运行,在index页面中单击”增加用户”或者“修改用户”超连接,结果都会直接打开登录页面。
Shiro实现登录认证 第一步:修改UserRealm.java中doGetAuthenticationInfo方法的代码如下:protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException{
System.out.println("========doGetAuthenticationInfo=================");
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
//模拟从数据库中获取用户名密码
User user = DB.getUserByUsername(userToken.getUsername());
if (null == user) { //用户不存在
return null; //抛出异常UnknownAccountException
}
//用户登录成功,将用户信息保存在Shiro的session中
SecurityUtils.getSubject().getSession()
.setAttribute("currentLoginedUser",user);
//不能(不建议)自己做密码认证,系统会自己做
// 第一个参数为完整用户信息,方便授权时查找用户的权限
return new SimpleAuthenticationInfo(user, user.getUserpwd(), "");
}
第二步:修改UserController类,为其添加如下代码:
@PostMapping("/login")
public String login(String username, String userpwd, Model model) {
//获取当前的用户
Subject subject = SecurityUtils.getSubject();
//封装用户的登录数据
UsernamePasswordToken token = new UsernamePasswordToken(username, userpwd);
try {
subject.login(token);
return "index"; //登录成功后打开首页
} catch (UnknownAccountException e) { //用户名不存在
model.addAttribute("msg", "用户名错误");
log.info(e.getMessage());
return "login";
} catch (IncorrectCredentialsException e) { //用户名不存在
model.addAttribute("msg", "密码错误");
log.info(e.getMessage());
return "login";
}
}
Shiro请求授权实现
第一步:修改UserRealm.java中doGetAuthenticationInfo方法,在其中添加授权的代码如下:
@Bean(name = "shiroFilterFactoryBean")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("dwSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
//添加shiro的内置过滤器
Map map = new LinkedHashMap();
//拦截
map.put("/user/add", "authc"); //必须认证了才能访问
map.put("/user/update", "authc");
//上面两个可以使用通配符 map.put("/user/*","authc");
//授权,若当前登录用户未授权则会跳转到授权页面
map.put("/user/add", "perms[user:add]");
map.put("/user/update", "perms[user:update]");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
//设置登录页面
shiroFilterFactoryBean.setLoginUrl("/login");
//设置未授权页面
shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");
return shiroFilterFactoryBean;
}
上面代码中的unauth是在templates目录下编写的页面:
DOCTYPE html>
未授权
未经授权,不能访问!
第二步:在DispatchController中添加如下代码:
@RequestMapping("/unauth")
public String unauth(){
return "unauth";
}
第三步:修改UserRealm中的doGetAuthorizationInfo方法,在其中添加获取当前用户权限的代码:
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("============doGetAuthorizationInfo==============");
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
Subject subject = SecurityUtils.getSubject();
User user = (User) subject.getPrincipal();
//模拟从数据库中查询出权限
Set permissions = DB.getAuths(user.getId());
simpleAuthorizationInfo.setStringPermissions(permissions);//添加权限
return simpleAuthorizationInfo;
}
部署项目运行,发现随着登录用户的不同,所能进行的操作也随之不同。
Shiro整合Thymeleaf 第一步:增加Maven依赖
com.github.theborakompanioni
thymeleaf-extras-shiro
2.0.0
第二步:修改配置类ShiroConfig,在其中添加Shiro整合thymeleaf的代码:
@Bean
public ShiroDialect getShiroDialect() {
ShiroDialect shiroDialect = new ShiroDialect();
return shiroDialect;
}
第三步:修改index.html页面
DOCTYPE html>
首页
登录
退出登录
增加用户
修改用户
部署项目,打开首页只显示登录超连接文字,随着登录用户的不同,后续打开的页面显示不同的文字。
Shiro整合MyBatis 第一步:添加Maven依赖
mysql
mysql-connector-java
com.baomidou
mybatisplus-spring-boot-starter
1.0.5
com.baomidou
mybatis-plus
3.4.0
第二步:后台数据表结构:
public class UserRealm extends AuthorizingRealm {
@Resource
private UserAuthService userAuthService;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("===========doGetAuthorizationInfo===============");
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
Subject subject = SecurityUtils.getSubject();
User user = (User) subject.getPrincipal();
//模拟从数据库中查询出权限
Set permissions = new HashSet();
List auths = userAuthService.getAuthsByUserId(user.getId());
for(Auth auth : auths){
permissions.add(auth.getCode());
}
simpleAuthorizationInfo.setStringPermissions(permissions);//添加权限
return simpleAuthorizationInfo;
}
@Resource
private UserService userService;
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException{
System.out.println("====doGetAuthenticationInfo==========");
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
//从数据库中获取用户信息
User user = userService.getUserByUsername(userToken.getUsername());
if (null == user) { //用户不存在
return null; //抛出异常UnknownAccountException
}
//用户登录成功,将用户信息保存在Shiro的session中
SecurityUtils.getSubject().getSession()
.setAttribute("currentLoginedUser",user);
//不能(不建议)自己做密码认证,系统会自己做
// 第一个参数为完整用户信息,方便授权时查找用户的权限
return new SimpleAuthenticationInfo(user, user.getUserpwd(), "");
}
}