1.首先理解shiro的三大核心要素:subject 用户、securityManager 管理所有用户、realm 连接数据库
2.idea创建springboot项目,导入shiro依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.8.0</version>
</dependency>
3.创建Reaml类,添加以下代码
public class UserRealm extends AuthorizingRealm {
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
return null;
}
}
接着创建ShiroConfig类,添加如下代码
@Configuration
public class ShiroConfig {
//shiroFilterFactoryBean:3
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean
(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager);
return bean;
}
//DefaultWebSecurityManager:2
/* 在使用@Autowire自动注入的时候,加上@Qualifier(“test”)可以指定注入哪个对象
可以作为筛选的限定符,我们在做自定义注解时可以在其定义上增加@Qualifier,用来筛选需要的对象。
*/
@Bean(name = "securityManager")
public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联realm
securityManager.setRealm(userRealm);
return securityManager;
}
//Real 对象,需要自定义:1
@Bean
public UserRealm userRealm(){
return new UserRealm();
}
}
4.实现登陆拦截,在shiroconfig类中的shiroFilterFactoryBean方法中加入以下代码
//添加shiro的内置过滤器
/*
anon:无需认证就可以访问
authc:必须认证了才能访问
user:必须拥有记住我功能才能用
perms:拥有对某个资源的权限才能访问
role:拥有某个角色权限才能访问
*/
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/**","XXX");
filterMap.put("/**","XXX");
bean.setFilterChainDefinitionMap(filterMap);
//设置登录的请求
//这里注意toLogin对应controller中的RequestMapping
bean.setLoginUrl("/toLogin");
5.实现用户认证,首先在controller下添加如下代码
@RequestMapping("/login")
public String login(String username,String password,Model model){
//获取当前用户
Subject subject = SecurityUtils.getSubject();
//封装用户的登录数据,令牌加密
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//捕获登录异常
try{
subject.login(token);//执行登录方法
return "index";
}catch (UnknownAccountException e){
model.addAttribute("msg","用户名错误");
return "login";
}catch (IncorrectCredentialsException e){
model.addAttribute("msg","密码错误");
return "login";
}
然后在UserRealm类中的doGetAuthenticationInfo方法认证中加入如下代码
//用户名,密码 从数据库中取,这里采用模拟数据库操作
String name ="XXX";
String password = "XXX";
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
if(!userToken.getUsername().equals(name)){
return null; //抛出异常 UnKnowAccountException
}
//密码认证,shiro做
return new SimpleAuthenticationInfo("",password,"");
}
先执行try中的login方法,跳到doGetAuthenticationInfo方法中,再返回try捕捉异常
6.整合Mybatis,先添加依赖
<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.2.8</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
编写yml配置,数据库、mybatis、druid相关操作
接着完善项目,建立pojo、mapper、service层
service接口类跟mapper类中的方法一样
@Service
public class UserServiceImpl implements UserService{
@Autowired
UserMapper userMapper;
@Override
public User queryUserByName(String user_name) {
return userMapper.queryUserByName(user_name);
}
}
修改UserRealm配置类
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
//连接数据库
User user = userService.queryUserByName(userToken.getUsername());
//密码认证,shiro做
if(user==null){
return null;
}
return new SimpleAuthenticationInfo("",user.getUser_password(),"");
7.实现功能授权,首先在shiroconfig配置类中的shiroFilterFactoryBean下,添加需授权的页面
//授权,正常情况下没有授权跳到说明未授权页面
filterMap.put("/add","perms[user:add]");
filterMap.put("/update","perms[user:update]");
针对未授权页面需跳到提示页面,并在shiroFilterFactoryBean下,添加未授权页面路径请求
//未授权页面
bean.setUnauthorizedUrl("/unauthorized");
接着针对用户表添加一个权限列
针对登录后的用户,拿到其所拥有的权限,修改doGetAuthenticationInfo方法中return new SimpleAuthenticationInfo(user,user.getUser_password(),"");
以此来获得用户
在UserReaml配置类中的doGetAuthorizationInfo方法中添加如下代码
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//拿到当前的对象
Subject subject = SecurityUtils.getSubject();
User currentUser = (User) subject.getPrincipal();
//设置当前用户的权限
info.addStringPermission(currentUser.getPerms());
return info;
8.shiro整合thymeleaf,导入依赖thymeleaf-extras-shiro
在shiroconfig配置类中加入以下代码
//整合shiroDialect: 用来整合shiro thymeleaf
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
在页面中加入以下代码
xmlns:shiro="http://www.thymeleaf.org/extras/shiro"
<div shiro:hasPermission="user:add">
#控制页面哪些功能只能登录授权后才可以显示
对于登录后的登录按钮的隐藏,可以用session进行获取,而session配置代码可以放在获取用户信息步骤后的模块中
Subject currentSubject = SecurityUtils.getSubject();
Session session = currentSubject.getSession();
session.setAttribute("loginUser",user);
然后在登录盒子内进行判断
<div th:if="${session.loginUser}==null">