基于maven的SSH项目结合shiro进行登录验证及权限管理功能

数据库关系:

需要用到的是function中的code属性


角色表

用户-角色关系表



1.在web包下的pom文件中配置shiro的支持包:

		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-all</artifactId>
			<version>1.2.2</version>
		</dependency>

2.在web.xml中配置shiro的过滤器,注意!!:shiroFilter需要放在shruts2的前面,我是放在struts2的前面,OpenSessionInViewFilter的后面

   <!-- 配置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>

3.在web包的resource包下配置spring-shiro.xm

(我起这个名字是因为我在web.xml中加载配置文件的方式是(classpath:spring-*.xml,需要注意的是,如果不起这个名字,需要chuagnjian 的shiro的xml文件在web.xml中能读到)

以下是spring-shiro.xml的代码

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"  
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-4.2.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-4.2.xsd 
	http://www.springframework.org/schema/util 
	http://www.springframework.org/schema/util/spring-util-4.2.xsd 
	">

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
	<!-- 注入安全管理器对象 -->
	<property name="securityManager" ref="securityManager"></property>
	<!-- 注入相关页面访问URL -->
	<property name="loginUrl" value="/Login.jsp" />
	<!-- 验证成功后要跳转的链接,一般不配置,跳转后的界面由action控制-->
	<!-- <property name="successUrl" value="user/login" /> -->
	<!--
		 通过unauthorizedUrl没有权限操作时跳转页面
		 解释:如果页面可以进入,但是页面上的按钮设置了权限,如果点击了且没有权限,会跳转到那个界面?
	-->
	<property name="unauthorizedUrl" value="/Login.jsp" />
	
	<!-- 注入url拦截规则,这一个需要自己配置,具体配置,过两天吧数据库发过来,在配置,这里是重点 -->
	<property name="filterChainDefinitions">
		<value>
			/css/*=anon
			/img/*=anon
			/layui/*=anon
			/statics/css/*=anon
			/statics/easyui/*=anon
			/statics/images/*=anon
			/statics/js/*=anon
			/statics/json/*=anon
			/index.jsp=anon
			/login=anon
			<!-- index/region_queryAllByPager=perms['region.query'] -->
			/*=authc
		</value>
	</property>
</bean>

<!-- 注入安全管理器对象 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
	<property name="realm" ref="dmsRealm"></property>
</bean>

<!-- 注册realm,自己写的DMS文件的路径 -->
<bean id="dmsRealm" class="cn.lichenyang.dms.web.inteceptor.DMSRealm">
</bean>


<!-- 开启shiro框架注解支持 -->
<bean id="defaultAdvisorAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
	<property name="proxyTargetClass" value="true"></property>
</bean>

<!-- 配置shiro框架提供的切面,用于创建代理对象 -->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor" />
</beans>

4.以下是action中的代码

package cn.lichenyang.dms.web.action;

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.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import com.opensymphony.xwork2.ActionSupport;

import cn.lichenyang.dms.entity.TUser;

@Controller
@Scope("prototype")//非单例
@Namespace("/user")//命名空间
public class Test extends ActionSupport{

	//form表单传过来的参数,通过用户对象来接收
	private TUser user;
	
	//页面使用/user/login请求该方法
	@Action(value="login",results={
			@Result(name="success",location="/WEB-INF/content/main.jsp"),
			@Result(name="login",location="/Login.jsp")
	})
	public String login() { 	
		//通过shiro进行登录验证
		//从session中获取生成的验证码
		String key = (String) ServletActionContext.getRequest().getSession().getAttribute("regcode");
		//登录界面传过来的验证码
		String checkcode = ServletActionContext.getRequest().getParameter("checkcode");
		//校验验证码是否输入正确
		if(StringUtils.isNotBlank(checkcode) && checkcode.equals(key)) {
			//以上是我判断验证码是否正确的代码,直接看if条件中的内容就行了
			
			//获取当前用户对象,状态为未认证
			Subject subject = SecurityUtils.getSubject();
			//创建用户对象,该token为Realm文件中的token,
			//AuthenticationToken为UsernamePasswordToken的父类,传入用户账号和密码到realm文件中进行判断用户权限
			AuthenticationToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword());
			try {
				//根据用户输入的账号密码进行登录验证,这一步只能通过subject的login方法进行验证
				subject.login(token);
			}catch(Exception e) {
				e.printStackTrace();
				//如果登录失败就返回登录界面
				return LOGIN;
			}
			//如果登录成功,就得到当前对象,并把当前对象存到session中
			TUser user = (TUser) subject.getPrincipal();
			ServletActionContext.getRequest().getSession().setAttribute("userLogin",user );
			return SUCCESS;
		
		}else {
			ServletActionContext.getRequest().setAttribute("msg", "验证码错误");
			return LOGIN;
		}
		
		/*
		//不采用shiro
		//验证// session中验证码
		String key = (String) ServletActionContext.getRequest().getSession().getAttribute("regcode");
		if (key == null || !key.equals(ServletActionContext.getRequest().getParameter("checkcode"))) {
            // 验证码无效
            ServletActionContext.getRequest().setAttribute("msg", "验证码错误");
            return LOGIN;
        }
		user = userService.login(user);
		if(user != null) {
			getSession().setAttribute("userLogin", user);
		}else {
			return LOGIN;
		}
		return SUCCESS;
		*/
	}
	
//=================================================================================================	
	//get,set方法
	public TUser getUser() {
		return user;
	}
	public void setUser(TUser user) {
		this.user = user;
	}
}

5.配置Realm文件

package cn.lichenyang.dms.web.inteceptor;

import java.util.List;

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.springframework.beans.factory.annotation.Autowired;

import cn.lichenyang.dms.dao.IAuthFunctionDao;
import cn.lichenyang.dms.dao.ITUserDao;
import cn.lichenyang.dms.entity.AuthFunction;
import cn.lichenyang.dms.entity.TUser;

public class DMSRealm extends AuthorizingRealm{

	@Autowired	//创建用户接口对象(接口中有根据用户名查询当前用户方法)
	private ITUserDao userDao;
	
	@Autowired	//这个是我的功能权限表中的内容,里面有我需要的功能权限的代码
	private IAuthFunctionDao functionDao;
	
	//认证方法
	//在自定义的Realm中的doGetAuthenticationInfo方法中
	//需要做的事:1.根据token进行查询然后检查对象是否为空以及其他自定义的条件,
	//		  2.最后封装成SimpleAuthenticationInfo返回就行了。
	@Override						
	//Action中是:AuthenticationToken token = new UsernamePasswordToken();,所以()用AuthenticationToken类型
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		// TODO Auto-generated method stub
		System.out.println("自定义realm中认证方法执行了。。。。。");
		//第一步是从token中取到身份信息
		UsernamePasswordToken passwordToken =  (UsernamePasswordToken)token;	//AuthenticationToken是UsernamePasswordToken的父类型
		//获得页面输入的用户名
		String username = passwordToken.getUsername();
		//根据用户名查询数据库中的密码
		TUser user = userDao.findUserByUserName(username);
		if(user == null) {
			return null;	//页面输入的用户不存在(第一步完成)
		}
		//简单认证信息对象				//一般登录时进行权限验证,所以都是这3个参数
		AuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
		return info;//(第二步完成)
	}
	
	//授权方法
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		// TODO Auto-generated method stub
		
		
		//获取当前登录用户对象
		TUser user = (TUser)SecurityUtils.getSubject().getPrincipal();	//自己随便选择哪一种
		//TUser user = (TUser)principals.getPrimaryPrincipal();	//以上2种获取对象的方式都行
		
		//根据当前登录用户查询数据库,获取实际对应的权限
		List<AuthFunction> list = null;		//创建一个权限功能的集合(因为我的功能不)
		
		if(user.getUsername().equals("admin")) {	//判断用户是否为超级管理员,如果是,就可以执行所有权限,如果不行只能执行自己的权限
			//超级管理员内容之用户,查询所有权限数据
			list=functionDao.findAll();	//可以执行所有权限
		}else {
			list=functionDao.queryById(user.getUserId());//只能执行自己的权限
		}
		
		//以下3步是创建权限
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		for (AuthFunction Function : list) {
			info.addStringPermission(Function.getCode());	//将权限放到shiro中
		}
		return info;	//返回这个权限
	}
}
6.接下来根据所用的角色进行登录就行了
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值