github克隆源代码:https://github.com/Lu-dashuai/shiro.git
参考视频(B站):https://www.bilibili.com/video/av33332282?p=6
1.目标:
1.认证拦截:
- 未登陆的用户都不能访问后台页面,访问的结果是跳转到登陆页面。
2.权限认证:
-
学生只能访问学生应该访问的页面。老师也同样。
-
表结构
-
项目结构
-
注意:
- 这里我只有用户表。其他表没有创建。角色是自己模拟的。
- 项目中与Emp有关的都可以删除,那些是测试框架的。
2.操作:
1.整合springboot、mybatis、redis、thyemleaf
- 我已将在github上上传了一个springboot、mybatis、redis、thyemleaf,整合版的干净框架。可以直接克隆到本地。具体克隆步骤:
https://blog.csdn.net/weixin_43067223/article/details/84632586 - 框架github地址:https://github.com/Lu-dashuai/springboot-mybatis-redis.git
- 直接克隆到本地就ok。
2.将项目spring和shiro的整合依赖导入
- 此时需要更改pom.xml文件
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
- 依赖已经导入
3.编写初步的shiro的配置类
- 在这之前请先观看所有的.html页面,看好跳转关系。
- 在java文件夹下新建com.aaa.rent.shiro目录;
- 在目录下创建一个类ShiroConfig;
- 给类加注解 @Configration :声明为配置类;
- 在类中写三个方法,分别:
- 创建ShiroFilterFactoryBean;
- 设置安全管理器
- 添加shiro的过滤器
- 被拦截后跳转登陆页面
- 未授权跳转页面
- 创建DefaultWebSecurityManager;
- 关联realm
- 创建Realm;
||
||
\ . /
- 创建ShiroFilterFactoryBean;
以上三个方法分别加上注解 @Bean;
- 在目录下创建一个UserRealm类,继承AuthorizingRealm
- 实现两个方法:
- doGetAuthorizationInfo:执行授权逻辑。
- 获取当前登陆的用户
- 通过用户名查当前用户
- 获取当前的权限字符
- 设置只有是这个字符才可以访问
- doGetAuthenticationInfo::执行认证逻辑。
- 编写shiro判断逻辑,判断用户名密码是否正确
- doGetAuthorizationInfo:执行授权逻辑。
ShiroConfig代码
package com.aaa.rent.shiro;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* className:ShiroConfig
* discription:
* author:luRuiHua
* createTime:2018-11-30 14:36
* 拦截器作用:如果没登陆或者用户名密码输错,登陆index.html失败,跳转到login.html
* 如果登陆成功,可以访问index.html
* 不能直接访问user/student----------student授权
* user/teacher---------teacher授权
* user/index
* 可以访问user/login
* user/toLogin
*
*/
@Configuration//配置类
public class ShiroConfig {
/**
* 1. 创建ShiroFilterFactoryBean;
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
//添加shiro的过滤器
//shiro的内置过滤器:可以实现权限的相关拦截
//常用的过滤器:
//1.anno:无需认证(登陆即可访问)
//2.authc:必须认证才可以访问
//3.user:如果使用remanberMe的功能就可以直接访问
//4.perms:该资源必须得到资源权限才可以访问
//5.role:该资源必须得到角色权限才可以访问
Map filterMap = new HashMap();
//必须登陆才可以访问
//设置哪些页面必须授权后才可以登陆
filterMap.put("/user/student","perms[2]");//学生页面
filterMap.put("/user/teacher","perms[1]");//老师页面
filterMap.put("/user/index","authc");//首页
//被拦截后跳转登陆页面
shiroFilterFactoryBean.setLoginUrl("/user/login ");
//未授权跳转页面
shiroFilterFactoryBean.setUnauthorizedUrl("/user/unAuth");
//将filterMap中的url和相关权限交给shiro框架管理
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
/**
* 2. 创建DefaultWebSecurityManager;
*/
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联realm
securityManager.setRealm(userRealm);
return securityManager;
}
/**
* 3. 创建Realm;
*/
@Bean(name = "userRealm")
public UserRealm getRealm() {
return new UserRealm();
}
/**
* 配置shiroDialect,用于thymeleaf和shiro标签配合使用
*/
@Bean
public ShiroDialect getShiroDialect() {
return new ShiroDialect();
}
}
UserRealm类
package com.aaa.rent.shiro;
import com.aaa.rent.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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import javax.xml.bind.SchemaOutputResolver;
import java.util.List;
import java.util.Map;
/**
* className:UserRealm
* discription:
* author:luRuiHua
* createTime:2018-11-30 14:41
*/
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 执行授权逻辑
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行授权逻辑");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//获取当前登陆的用户
Subject subject = SecurityUtils.getSubject();
//获取用户名
String userName = subject.getPrincipal()+"";
//通过用户名查当前用户
List<Map> maps = userService.selectUserList(userName);
//获取当前的权限字符
String roleId = maps.get(0).get("ROLE_ID")+"";
//设置只有是这个字符才可以访问
info.addStringPermission(roleId);
return info;
}
/**
* 执行认证逻辑
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行认证逻辑");
//编写shiro判断逻辑,判断用户名密码是否正确
UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
String username = token.getUsername();
//1.判断用户名
List<Map> mapList = userService.selectUserList(token.getUsername());
if (mapList.size() == 0) {
return null;
} else {
return new SimpleAuthenticationInfo(username, mapList.get(0).get("PASSWORD"),"");
}
}
}
5.UserController.java中的逻辑
- 获取前台页面登陆的账号和密码
- 获取subject
- 封装用户数据
- 执行登陆方法
- 登陆成功,跳到欢迎页面
- 用户名不存在的异常
- 用户名和密码错误
/**
* 跳转欢迎页面
* @return
*/
@RequestMapping("/toLogin")
public String toLogin(String userName, String passWord, Model model) {
System.out.println("账号是:"+userName);
//shiro的关键代码,执行认证功能
//1.获取subject
Subject subject = SecurityUtils.getSubject();
//2.封装用户数据
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userName, passWord);
//3.执行登陆方法
try {
//登陆成功
subject.login(usernamePasswordToken);
model.addAttribute("msg","登陆成功");
//跳到欢迎页面
return "back/welcome";
} catch (UnknownAccountException e) {//用户名不存在的异常
model.addAttribute("msg","用户名不存在");
return "login";
} catch (IncorrectCredentialsException e) {//用户名不存在的异常
model.addAttribute("msg","用户名和密码错误");
return "login";
}
}
如有错误,多多指正,感谢观看!