Shiro配置,整合SpringBoot、Hibernate、Thymeleaf
shiro有什么用
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理
Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果系统默认的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现
三个核心组件
- Subject
- Subject:即“当前操作用户”,但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物,它仅仅意味着“当前跟软件交互的东西”
- Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作
- SecurityManager
- 它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务
- Realms
- Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”,也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息
- Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro,当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权,配置多个Realm是可以的,但是至少需要一个
搭建SpringBoot+Web+Mysql+Hibernate+Thymeleaf+Druid项目
导入依赖
<!-- shiro-spring -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.8.0</version>
</dependency>
<!-- shiro-thymeleaf-->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
<!--添加ehcache -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.4.0</version>
</dependency>
配置Shiro
- 创建ShiroConfig配置类对应上面讲的三个核心组件
package com.springboot.huyitest.config;
import java.util.LinkedHashMap;
import java.util.Map;
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 at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
@Configuration
public class ShiroConfig {
//创建realm对象,需要自定义类
@Bean
public UserRealm userRealm(){
return new UserRealm();
}
//DafaultWebSecurityManager
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
DefaultWebSecurityManager securityManager =new DefaultWebSecurityManager();
//关联userRealm
securityManager.setRealm(userRealm);
return securityManager;
}
//ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
/*
* anon : 无需认证直接访问
* authc : 必须认证才能访问
* user : 必须有记住我功能才能使用
* perms : 拥有对某个资源的权限才能访问
* role : 拥有某个角色的权限才能访问
*/
//添加Shiro的内置过滤器
Map<String,String> filterMap=new LinkedHashMap<>();
//这里可以使用通配符*,下面表示需要用户携带user:add/user:delet才可以访问对应页面
filterMap.put("/addUser", "perms[user:add]");
filterMap.p ut("/deletUser", "perms[user:delet]");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
//背拦截后跳到的页面
shiroFilterFactoryBean.setLoginUrl("/logoin");
//无授权跳转的页面
shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");
return shiroFilterFactoryBean;
}
@Bean //shiroDialect:用来整合shiro thymeleaf
public ShiroDialect getShiroDialect() {
return new ShiroDialect();
}
}
- 创建Realm类
package com.springboot.huyitest.config;
import org.apache.shiro.SecurityUtils;
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.authc.UsernamePasswordToken;
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 com.springboot.huyitest.pojo.Permissions;
import com.springboot.huyitest.pojo.Role;
import com.springboot.huyitest.pojo.User;
import com.springboot.huyitest.service.permissionsService;
import com.springboot.huyitest.service.userService;
/*
* 自定义的realm类
* 需要继承AuthorizingRealm
* */
public class UserRealm extends AuthorizingRealm{
@Autowired
userService userservice;
@Autowired
permissionsService permissionsService;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
System.err.println("执行了授权");
SimpleAuthorizationInfo info= new SimpleAuthorizationInfo();
//拿到登录的用户
Subject subject= SecurityUtils.getSubject();
Role role = (Role)subject.getPrincipal();
System.err.println(role.getId());
info.addRole(role.getRolename());
for(Permissions permissions:permissionsService.getPermissionsById(role.getId())) {
System.err.println(permissions.getPermissionsName());
//这里用到的getPermissionsName()方法是下面整合时候写的sql
info.addStringPermission(permissions.getPermissionsName());
}
return info;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// TODO Auto-generated method stub
System.err.println("执行了认证");
UsernamePasswordToken userToken=(UsernamePasswordToken)token;
//账号认证,这里用到的getUser方法是下面整合时写的hql
User user = userservice.getUser(userToken.getUsername());
if(user!=null) {
//密码认证是由shiro来做的
return new SimpleAuthenticationInfo(user.getRoles(),user.getPassWord(),"");
}
return null;
}
}
Hibernate整合Shiro
- 这里对应上面创建Realm类中用到的认证账号和用户密码
package com.springboot.huyitest.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import com.springboot.huyitest.pojo.User;
public interface userDao extends JpaRepository<User,Long>,JpaSpecificationExecutor<User>{
@Query("from User u where u.userName =?1")
User getUser(String name);
}
注意 :别忘了创建service层,上面用的@Autowired注入是注入的对应service层的方法
- 这里对应上面创建Realm类中用到的getPermissionsById()方法
package com.springboot.huyitest.dao;
import java.util.Set;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import com.springboot.huyitest.pojo.Permissions;
public interface permissionsDao extends JpaRepository<Permissions,Long>,JpaSpecificationExecutor<Permissions>{
@Query(nativeQuery = true,value="SELECT id,permissions_name,description FROM permissions WHERE id IN (SELECT permissions_id FROM role_permissions WHERE role_id=?1)")
Set<Permissions> getPermissionsById(Long RoleId);
}
注意:别忘了写pojo实体层
Thymeleaf整合Shiro
- xmlns:th="http://www.thymeleaf.org"
- xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-shiro"
<!DOCTYPE html>
<html
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<div shiro:hasPermission="user:delet">
<a th:href="@{/deletUser}" style="color: red;">删除页面</a>
</div>
<div shiro:hasPermission="user:add">
<a th:href="@{/addUser}">添加页面</a>
</div>
<div>
<a th:href="@{/logout}">退出登录</a>
</div>
</body>
</html>