javaEE shiro框架,权限控制。基于Spring框架的shiro认证/授权。URL过滤进行权限控制

shiro框架的Jar包下载:https://pan.baidu.com/s/1GCeHV_5T4uP2rGZfUEwl3A  密码:bgr0

权限控制的方式:
方式一:通过过滤器或Struts2的拦截器实现权限控制
方式二:为Struts2的Action加入注解(标识),然后为Action创建代理对象;代理对象进行权限校验,校验通过后通过反射调用目标方法。

shiro框架可以进行认证、授权、会话管理、加密等。

shiro框架认证/授权流程:

web.xml(web核心配置文件,配置Spring提供的shiro过滤器):

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <display-name>MyWeb</display-name>
  
  <!-- 配置spring框架提供的用于整合shiro框架的过滤器。(要在Struts2的过滤器前面配置) -->
  <filter>
  	<filter-name>shiroFilter</filter-name>
  	<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>shiroFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <!-- 配置过滤器,解决hibernate延迟加载no-session的问题 -->
  <filter>
  	<filter-name>openSessionInView</filter-name>
  	<filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>openSessionInView</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <!-- 通过上下文参数指定spring配置文件位置 -->
  <context-param>
  	<param-name>contextConfigLocation</param-name>
  	<param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  
  <!-- 配置spring框架的监听器 -->
  <listener>
  	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  
  <!-- 配置struts2的过滤器 -->
  <filter>
  	<filter-name>struts2</filter-name>
  	<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>struts2</filter-name>
  	<url-pattern>/*</url-pattern>
  	<dispatcher>REQUEST</dispatcher>
  	<dispatcher>FORWARD</dispatcher>
  </filter-mapping>
  
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

applicationContext.xml(Spring的核心配置文件):

<?xml version="1.0" encoding="UTF-8"?>
<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"
	xmlns:jaxws="http://cxf.apache.org/jaxws"
	xmlns:soap="http://cxf.apache.org/bindings/soap"
	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.xsd
						http://www.springframework.org/schema/aop
						http://www.springframework.org/schema/aop/spring-aop.xsd
						http://www.springframework.org/schema/tx 
						http://www.springframework.org/schema/tx/spring-tx.xsd
						http://cxf.apache.org/bindings/soap 
						http://cxf.apache.org/schemas/configuration/soap.xsd
						http://cxf.apache.org/jaxws 
						http://cxf.apache.org/schemas/jaxws.xsd
						">

	<!-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -->

	<!-- ====================================================================== -->
		
	<!-- 配置shiro框架的过滤器工厂对象。"shiroFilter"要和web.xml中配置的过滤器名保持相同 -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<!-- 注入安全管理器对象 -->
		<property name="securityManager" ref="securityManager"/>
		<!-- 注入访问相关页面的URL -->
		<property name="loginUrl" value="/login.jsp"/>
		<property name="successUrl" value="/index.jsp"/>
		<property name="unauthorizedUrl" value="/unauthorized.jsp"/>  <!-- 权限不足的错误提示页 -->
		<!--注入URL拦截规则 -->
		<property name="filterChainDefinitions">
			<value>
				/css/** = anon   <!-- anon是过滤器的别名(简称)。 两个*表示递归所有层子目录 -->
				/js/** = anon    <!-- 过滤器有次序之分,依次匹配过滤器 -->
				/images/** = anon
				/validatecode.jsp* = anon
				/login.jsp = anon
				/userAction_login.action = anon
				/page_base_staff.action = perms["staff-list"]  <!-- 必须先认证(登录)后,才会进行授权(权限分配)。"staff-list"是自定义的权限名 -->
				/* = authc    <!-- authc表示是否已认证(已登录) -->
			</value>
		</property>
	</bean>
	
	<!-- 注册安全管理器对象 -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="bosRealm"/>  <!-- 将Realm注入安全管理器 -->
	</bean>
	
	<!-- 注册realm -->
	<bean id="bosRealm" class="com.xxx.bos.realm.BOSRealm"></bean>
</beans>

UserAction.java(Struts2的Action):

package com.xxx.bos.web.action;

import java.io.IOException;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.struts2.ServletActionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.xxx.bos.domain.User;
import com.xxx.bos.service.IUserService;
import com.xxx.bos.utils.BOSUtils;
import com.xxx.bos.utils.MD5Utils;
import com.xxx.bos.web.action.base.BaseAction;

@Controller
@Scope("prototype")
public class UserAction extends BaseAction<User> {
	
	/**
	 * 用户登录,使用shiro框架提供的方式进行认证操作
	 */
	public String login(){
		//使用shiro框架提供的方式进行认证操作
		Subject subject = SecurityUtils.getSubject();//获得当前用户对象,状态为"未认证"
		//创建用户名密码令牌对象
		AuthenticationToken token = new UsernamePasswordToken(model.getUsername(),MD5Utils.md5(model.getPassword()));//创建用户名密码令牌对象
		try{
			//认证(登录) (和注入了Realm的安全管理器(SecurityManager)进行交互,认证)
			subject.login(token);  //登录失败(认证失败)就会抛异常
		}catch(Exception e){  //如果抛异常说明登录失败(认证失败)。 没有该用户和用户密码错误抛出的异常是不同的,可以分开catch。
			e.printStackTrace();
			return LOGIN;
		}
		//没抛异常说明认证成功
		User user = (User) subject.getPrincipal();  //返回的是实例化SimpleAuthenticationInfo()时的第一个参数
		ServletActionContext.getRequest().getSession().setAttribute("loginUser", user);
		return HOME;
	}
	
}

BOSRealm.java(继承AuthorizingRealm):

package com.xxx.bos.realm;

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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import com.xxx.bos.dao.IUserDao;
import com.xxx.bos.domain.User;

public class BOSRealm extends AuthorizingRealm{
	@Autowired
	private IUserDao userDao;
	
	//认证方法
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		System.out.println("自定义的realm中认证方法执行了。。。。");
		UsernamePasswordToken passwordToken = (UsernamePasswordToken)token;
		//获得页面输入的用户名
		String username = passwordToken.getUsername();
		//根据用户名查询数据库中的密码
		User user = userDao.findUserByUsername(username);
		if(user == null){
			//页面输入的用户名不存在
			return null;  //return null 说明认证失败,安全管理器(SecurityManager)就会抛异常
		}
		//简单认证信息对象  (参数一:要传给subject的内容(subject.getPrincipal()获取的内容)。参数二:数据库中的密码;参数三:类名"BOSRealm")
		AuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
		//框架负责比对数据库中的密码和页面输入的密码是否一致
		return info;  //交给安全管理器(SecurityManager)去比对密码。比对不一致也会抛异常(认证失败)。
	}

	//授权方法
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		//为用户授权 (可以根据登录用户,查询数据库来确定该用户所拥有的权限)
		info.addStringPermission("staff-list");  //"staff-list"和applicationContext.xml(Spring配置文件)中配置的perms["staff-list"]中的名字对应。  		
		//TODO 需要根据当前登录用户查询数据库,获取实际对应的权限

		//获取当前登录用户的两种方式
		//User user = (User) SecurityUtils.getSubject().getPrincipal();
		//User user2 = (User) principals.getPrimaryPrincipal();
		return info;
	}
}

applicationContext.xml(Spring的核心配置文件)中的shiro过滤器:

猜你喜欢

转载自blog.csdn.net/houyanhua1/article/details/82714820