Shiro(五)——Shiro整合SSM入门完整案例

版权声明:本文为博主原创文章,未经博主允许不得转载。 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> 

11)启动测试即可

猜你喜欢

转载自blog.csdn.net/qq_34598667/article/details/84679563
今日推荐