版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34598667/article/details/84679563
过滤器
当 Shiro 被运用到 web 项目时,Shiro 会自动创建一些默认的过滤器对客户端请求进行过滤。以下是 Shiro 提供的过滤器:
过滤器简称 | 对应的Java类 | 解释 |
---|---|---|
anon | org.apache.shiro.web.filter.authc.AnonymousFilter | 匿名访问 |
authc | org.apache.shiro.web.filter.authc.FormAuthenticationFilter | 需要认证才能访问 |
authcBasic | org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter | 需要httpBasic认证 |
perms | org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter | 需要拥有指定权限认证 |
port | org.apache.shiro.web.filter.authz.PortFilter | 需要使用指定端口 |
rest | org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter | 指定请求方式访问 |
roles | org.apache.shiro.web.filter.authz.RolesAuthorizationFilter | 需要拥有指定角色 |
ssl | org.apache.shiro.web.filter.authz.SslFilter | 需要使用https协议 |
user | org.apache.shiro.web.filter.authc.UserFilter | 需要认证或者通过我才能访问 |
logout | org.apache.shiro.web.filter.authc.LogoutFilter | 注销,可以当做固定配置 |
noSessionCreation | org.apache.shiro.web.filter.session.NoSessionCreationFilter | — |
举例:
案例 | 解释 |
---|---|
/admin/** = anon | 表示该uri可以匿名访问(不用认证,直接访问) |
/admin/** = authc | 表示该uri需要登录认证才能访问 |
/admin/** = authcBasic | 表示该uri需要httpBasic认证才能访问 |
/admin/** = perms[user:add:*] | 表示该uri需要认证用户拥有user:add:*权限才能访问 |
/admin/** = port[8088] | 表示该uri需要使用8088端口 |
/admin/** = rest[user] | 相当于/admin/** = perms[user:method],其中method表示get,post,delete等提交方式 |
/admin/** = roles[admin] | 表示该uri需要认证用户拥有admin角色才能访问 |
/admin/** = ssl | 表示该uri需要使用https协议 |
/admin/** = user | 表示该uri需要认证或通过记住我才能访问 |
注意:
anon,authcBasic,auchc,user 是认证过滤器。
perms,roles,ssl,rest,port 是授权过滤器。
整合Spring案例
1)先使用maven创建项目,搭建好如下SSM开发环境
数据库
项目结构
2)添加依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.2.3</version>
</dependency>
3)新建登录界面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'login.jsp' starting page</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/user/login"
method="post">
<input type="text" name="username"/><br>
<input type="password" name="pwd"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
4)编写处理登录的UserController
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/login")
public String login(String username,String pwd,HttpServletRequest req){
Subject subject=SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken(username, pwd);
try{
subject.login(token);
}catch(AuthenticationException e){
System.out.println("登录失败!!!");
e.printStackTrace();
}
System.out.println("登录成功!!!");
return "jsp/main";
}
}
5)编写业务层UserService接口以及其实现类
UserService接口
public interface SysUserService {
/**
* @param loginName
* @return
*/
SysUser findByLoginName(String loginName);
}
UserServiceImpl实现类
@Service
public class SysUserServiceImpl implements SysUserService{
@Resource
private SysUserMapper sysUserMapper;
@Override
public SysUser findByLoginName(String loginName) {
return sysUserMapper.findByLoginName(loginName);
}
}
6)编写逆向工程生成的SysUserMapper接口和xml映射文件中
SysUserMapper接口:
/**
* @param loginName
* @return
*/
SysUser findByLoginName(@Param("loginName")String loginName);
SysUserMapper.xml映射文件:
<select id="findByLoginName" resultType="com.oak.shiro.pojo.SysUser">
select user_id userId,login_name loginName,password from `sys_user` where login_name=#{loginName}
</select>
7)自定义realm
public class CustomRealm extends AuthorizingRealm{
@Resource
private SysUserService sysUserService;
@Resource
private SysRoleService sysRoleService;
@Resource
private SysPermisService sysPermisService;
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
//token是用户输入的
//1、从token中取出身份信�?
String loginName=(String) token.getPrincipal();
//2、从数据库查到密码,散列�?取上面测试生成的散列�?
SysUser sysUser=sysUserService.findByLoginName(loginName);
// 模拟从数据库获取salt
String salt = "qwerty";
//上边散列值和盐对应的明文�?23
Session session = SecurityUtils.getSubject().getSession();
session.setAttribute("sysUser",sysUser);
//如果查询到则返回认证信息AuthenticationInfo
SimpleAuthenticationInfo simpleAuthenticationInfo=new SimpleAuthenticationInfo(
loginName,sysUser.getPassword(),ByteSource.Util.bytes(salt),this.getName());
return simpleAuthenticationInfo;
}
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
Session session = SecurityUtils.getSubject().getSession();
SysUser sysUser=(SysUser) session.getAttribute("sysUser");
System.out.println("##############"+sysUser);
//获取身份信息
// 权限信息对象,用来存放查出的用户的所有的角色(role)及权限(permission)等
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
if(sysUser!=null){
info.addRoles(getUserRoles(sysUser.getUserId()));
info.addStringPermissions(getUserPermissions(sysUser.getUserId()));
}
return info;
}
//得到用户权限
private Set<String> getUserPermissions(int userId) {
List<SysPermis> permisList = sysPermisService.findByUserId(userId);
Set<String> permiss = new HashSet<>();
if (CollectionUtils.isEmpty(permisList)) {
return permiss;
}
for (SysPermis permis : permisList) {
permiss.add(permis.getPermisCode());
}
return permiss;
}
//得到用户角色集合
private Set<String> getUserRoles(int userId){
List<SysRole> roleList=sysRoleService.findByUserId(userId);
Set<String> roles=new HashSet<String>();
//如果是空就直接返回
if(CollectionUtils.isEmpty(roles)){
return roles;
}
//如果不是空就得到角色编号添加进集合中
for (SysRole role : roleList) {
roles.add(role.getRoleCode());
}
return roles;
}
//init-method 配置.
public void setCredentialMatcher(){
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("MD5");//MD5算法加密
credentialsMatcher.setHashIterations(1024);//1024次循环加�?
setCredentialsMatcher(credentialsMatcher);
}
}
8)applicationContext-shiro.xml配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置 Shiro 的 SecurityManager Bean. -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="customRealm"/>
</bean>
<!-- 配置 Bean 后置处理器: 会自动的调用和 Spring 整合后各个组件的生命周期方法. -->
<bean id="lifecycleBeanPostProcessor"
class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- 配置 ShiroFilter bean: 该 bean 的 id 必须和 web.xml 文件中配置的 shiro filter 的 name 一致 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 装配 securityManager -->
<property name="securityManager" ref="securityManager"/>
<!-- 配置登陆页面 -->
<property name="loginUrl" value="/login.jsp"/>
<!-- 登陆成功后的一面 -->
<property name="successUrl" value="/index.jsp"/>
<property name="unauthorizedUrl" value="/unauthor.jsp"/>
<!-- 具体配置需要拦截哪些 URL, 以及访问对应的 URL 时使用 Shiro 的什么 Filter 进行拦截. -->
<property name="filterChainDefinitions">
<value>
<!-- 对静态资源设置允许匿名访问 -->
/images/** = anon
/js/** = anon
/css/** = anon
<!-- 可匿名访问路径,例如:验证码、登录连接、退出连接等 -->
/user/login = anon
<!-- 其他路径需要认证才能访问 -->
/** =authc
</value>
</property>
</bean>
</beans>
6)在shiro配置文件中添加自定义realm的bean
<!-- 配置进行授权和认证的 Realm,要新增一个java类来实现,下面会有,class=包名.类名,init-methood是初始化的方法 -->
<bean id="customRealm" class="shiro.CustomRealm" init-method="setCredentialMatcher"></bean>
9)web.xml配置
<!-- shiro filter配置shiro过滤器-->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<!--默认flase :false为交给spring容器管理,true交给servlet容器管理-->
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
10)编写登录之后的main.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>后台首页</title>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
$(function(){
$.ajax({
// 提交数据的类型 POST GET
type : "POST",
// 提交的网址
url : "${pageContext.request.contextPath }/menu/userMenu",//
// 返回数据的格式
datatype : "json",
// 成功返回之后调用的函数
success : function(data) {
console.log(data);
// $("#msg1").html(decodeURI(data));
var result = eval(data);
console.log(result);
handleMenu(result.menuList);
},
});
});
//打印菜单
function handleMenu(menuList) {
var menuUl = "";
for (var i = 0; i < menuList.length; i++) {
menuUl = "<li><a href=" + menuList[i].menuUrl + ">"
+ menuList[i].menuText + "</a></li>";
$("#menuUl").append(menuUl);
}
}
</script>
</head>
<body>
<ul id="menuUl"></ul>
</body>
</html>