SSM框架导入shiro安全框架

shiro核心功能:登录,授权验证
shiro:核心组件:①Subject:与程序交互的对象
②SecurityManager:安全管理器,shiro的核心;所有与安全相关的操作都与SecurityManager交互;且管理着所有的Subject
③Realms:Shiro从Realm获取安全数据,SecurityManager验证用户身份,必须要从Realm获取相应的用户信息
④ShiroFilterFactoryBean:指定路径拦截规则
1.创建ssm框架工程
2.数据库:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.实体类和方法:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
给大家看一下我建立的包路径,防止后面部分代码导包看不明白在这里插入图片描述

4.在pom.xml里导入shiro相关的jar包

<!--Shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.3.2</version>
</dependency>

5.在工程中创建继承ShiroFilterFactoryBean的类:

package com.xcxy.shiro.factory;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.shiro.config.Ini;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.web.config.IniFilterChainResolverFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.xcxy.user.dao.MenuMapper;

import com.xcxy.user.entity.Menu;
import com.xcxy.user.entity.Role;  

public class MyShiroFilterFactoryBean extends ShiroFilterFactoryBean{

		@Autowired
		private MenuMapper mm;
		//{0}为占位符  ROLE_STRING是用于字符串拼接
		private static final String ROLE_STRING = "roles[{0}]";
		//默认权限
		public static  String filterChainDefinitions="";
		
		/*重写设置过滤规则*/
	    @Override
	    public void setFilterChainDefinitions(String definitions) {
	    	System.out.println("$$$$$$$$$$$$$$");
	    	//每次都付给filterChainDefinitions
	    	filterChainDefinitions = definitions;
	        Ini ini = new Ini();
	        ini.load(definitions);
	        //did they explicitly state a 'urls' section?  Not necessary, but just in case:
	        Ini.Section section = ini.getSection(IniFilterChainResolverFactory.URLS);
	        if (CollectionUtils.isEmpty(section)) {
	            //no urls section.  Since this _is_ a urls chain definition property, just assume the
	            //default section contains only the definitions:
	            section = ini.getSection(Ini.DEFAULT_SECTION_NAME);
	        }
	        Map<String,String[]> permsMap = new HashMap<String, String[]>();
	        /*查询菜单表*/
	        List<Menu> menus=mm.findMenuAll();
	        for (Menu menu : menus) {
	        	/*获取每个权限对应的所有角色*/
				List<Role> rs=menu.getRoles();
				String[] roleNames=new String[rs.size()];
				/*获取角色名集合*/
				for(int i=0;i<rs.size();i++){
					roleNames[i]=rs.get(i).getrName();			
				}
				/*键值对存储,相当于此url哪些角色可以进入*/
				permsMap.put(menu.getmUrl(), roleNames);
			}
	        //遍历拿出map中存放的URL和角色名
	        for (String url : permsMap.keySet()) {
				 System.out.println("路径:"+url);
				 //通过路径取得对应的角色
				 String[] roles = permsMap.get(url);//map中,根据key的内容获取其value
				 StringBuilder sb = new StringBuilder();
				 for (String role : roles) {
					 sb.append(role).append(",");
				}
				 //截取最后一个,如(admin,test,)
				 String str = sb.substring(0,sb.length()-1);
				 System.out.println("str:"+str+"%%%%%%%%%%%");
				 System.out.println(permsMap+"************");
				 //把对应的路径以及权限放到section中, MessageFormat.format(ROLE_STRING, str) 替换占位符{0}  
				 System.out.println("MessageFormat.format(ROLE_STRING, str):"+MessageFormat.format(ROLE_STRING, str));
				 section.put(url, MessageFormat.format(ROLE_STRING, str));
			}
	        /*代表所有的页面都需要权限才能访问*/
	        section.put("/**", "authc");
	        setFilterChainDefinitionMap(section);
	    }
	    
	
}

6.创建自定义类数据源:

package com.xcxy.shiro.realm;

import java.util.HashSet;
import java.util.Set;

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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import com.xcxy.user.dao.UserMapper;
import com.xcxy.user.entity.Role;
import com.xcxy.user.entity.User;

public class MyRealm extends AuthorizingRealm{
	@Autowired
	private UserMapper usermapper;
	
	/**
	 * 
	 * 授权方法
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		// 1. 从PrincipalCollection中来获取登陆用户的信息
		Object principal = principals.getPrimaryPrincipal();
		System.out.println("当前登陆的用户:"+principal);
		// 2. 利用登陆的用户信息来获取用户当前的角色以及权限(可能查询数据库)	
		Set<String> set = new HashSet<String>();
        //查询User通过账号
		User user = usermapper.findUserByUserName((String)principal);
		System.out.println(user+"*********");
		//得到User对应的角色
		Role role = user.getRole();
		//将角色放进集合中
		set.add(role.getrName());		
		System.out.println("set里的值:"+set);
		// 3. 创建SimpleAuthorizationInfo,并设置其reles属性
		SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
		simpleAuthorizationInfo.addRoles(set);
		// 4. 返回SimpleAuthorizationInfo对象
		return simpleAuthorizationInfo;
	}

	/**
	 * 认证方法
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		// 从token拿到用户名
		String userName = (String) token.getPrincipal();
		//通过用户名去数据库查询
		System.out.println("============================="+userName);
		User user=usermapper.findUserByUserName(userName);
		Subject currentUser = SecurityUtils.getSubject();
		Session session = currentUser.getSession();
		//发送用户名-main页面欢迎xx登录
		session.setAttribute("username", user.getuName());
		// 获取盐,通常用账号
		ByteSource credentialsSalt = ByteSource.Util.bytes(userName);
		// 盐值加密——密码不易被破解
		SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userName,user.getuPassword(),credentialsSalt,getName());
		// SimpleAuthenticationInfo simpleAuthenticationInfo = new
		// SimpleAuthenticationInfo(user,
		// "64c8b1e43d8ba3115ab40bcea57f010b",getName());
		return simpleAuthenticationInfo;
	}

}


}

7.创建加密工具类(需要测试类获取加密后的密码存入数据库):

package com.xcxy.shiro.util;

import org.apache.shiro.crypto.hash.SimpleHash;

/**
 * 加密工具类
 * @author john
 *
 */
public class MD5 {
	//加密类型
	private static String hashName="MD5";
	//加密次数
	private static int hashNum=1024;
	public static Object getMD5(String pwd,String salt){
		Object obj=new SimpleHash(hashName, pwd, salt, hashNum);
		return obj;
		
	}

}

8.创建自定义过滤器

package com.xcxy.shiro.util;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;

public class UserRolesAuthorizationFilter extends AuthorizationFilter{

@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
Subject subject = getSubject(request, response);
String[] rolesArray = (String[]) mappedValue;
 
if (rolesArray == null || rolesArray.length == 0) { //没有角色限制,有权限访问
return true;
}
for (int i = 0; i < rolesArray.length; i++) {
if (subject.hasRole(rolesArray[i])) { //若当前用户是rolesArray中的任何一个,则有权限访问
return true;
}
}
return false;
}


}

9.在applicationContext.xml添加shiro相关的配置

<!-- shiro配置 -->
	<bean id="myRealm" class="com.xcxy.shiro.realm.MyRealm"> <!-- 配置自定义类数据源 -->
	 	<property name="credentialsMatcher">
            <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                <property name="hashAlgorithmName" value="MD5"></property> <!-- 加密算法的名称 -->
                <property name="hashIterations" value="1024"></property> <!-- 配置加密的次数 -->
            </bean>
        </property>
	</bean>
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="myRealm"></property>
	</bean>
	<bean
		class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
		<property name="securityManager" ref="securityManager"></property>
	</bean>
	<!-- 配置核心过滤器 -->
	<bean id="shiroFilter" class="com.xcxy.shiro.factory.MyShiroFilterFactoryBean"><!-- 自定义继承ShiroFilterFactoryBean的类 -->
		<property name="securityManager" ref="securityManager"></property>
		<!-- 除anon权限以外的所有没登陆的访问都到这 -->
		<property name="loginUrl" value="/system/gologin" />
		<!-- 登陆成功后显示的页面 -->
		<property name="successUrl" value="/system/main" />
		<!-- 登录后访问没有权限的页面后跳转的页面 -->
		<property name="unauthorizedUrl" value="/system/error" />
		<property name="filters">
	    	<map>
	    	    <entry key="roles" value-ref="roleOrFilter"/>
	    	</map>
	    </property>
	   	<property name="filterChainDefinitions">
			<value>
				/static/**=anon
				/system/login=anon 		 <!-- anon表示匿名访问,就是不用登录 -->
				/system/gologin=anon
				/system/getVerifyCode=anon <!-- 获取验证码 -->
				/system/register=anon	<!-- 注册 -->
				/system/loginout=logout
				 <!-- anon表示匿名访问,就是不用登录 -->
				<!-- /**/*.do = authc --> 		<!-- authc表示要登录后,才能访问 -->
			</value>
		</property>
	</bean>
	<!-- 自定义的过滤器,用来判断当前用户是否是roleOrFilter["comm,test"]中的某个角色 -->
    <bean id="roleOrFilter" class="com.xcxy.shiro.util.UserRolesAuthorizationFilter" />

10.在web.xml中配置shiro过滤器:

<!-- 配置shiro的过滤器 -->
	<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>

11.在WEB-INFO创建页面:
在这里插入图片描述
12.controller层

/**
	 * 登录验证
	 * @return
	 */
	@PostMapping("/login")
	public String login(String username,String password,HttpServletRequest request){
Subject subject=SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken(username,password);
		try {
			/*用户验证*/
			subject.login(token);
/*登录成功,进入主页面*/
			return "system/main";
		} catch (AuthenticationException e) {
			/*登录失败,返回登录页面*/
			e.printStackTrace();
			request.getSession().setAttribute("error", "账号密码错误");
			return "system/login";
		}	
	}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值