shiro安全框架的使用流程


最近學了shiro安全框架流程,在這里梳理一下shiro的工作流程和一些代碼,方便以后使用的時候,能快速找到對應的代碼。

 

要使用這個shiro框架,還要新建兩張表 t_authority(權限表)和t_role_authority(角色權限表)

 

1.先在porm.xml中引入四個jar包,分別是shiro-core(shiro核心包)、shiro-web(shiro服務包)、shiro-spring(shiro和spring整合包)和shiro-ehcache(shiro緩存包)

<shiro.version>1.3.2</shiro.version

	 <dependency>
		    <groupId>org.apache.shiro</groupId>
		    <artifactId>shiro-core</artifactId>
		    <version>${shiro.version}</version>
		</dependency>
		<dependency>
		    <groupId>org.apache.shiro</groupId>
		    <artifactId>shiro-web</artifactId>
		    <version>${shiro.version}</version>
		</dependency>
		<dependency>
		    <groupId>org.apache.shiro</groupId>
		    <artifactId>shiro-spring</artifactId>
		    <version>${shiro.version}</version>
		</dependency>
		<dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>${shiro.version}</version>
        </dependency>

2.在web.xml中配置filter(攔截器),攔截所有URL請求路徑。

			<!-- shiro過濾器定義 -->
	<filter>
	    <filter-name>shiroFilter</filter-name>
	    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	    <init-param>
	        <!-- 該值缺省為false,表示生命周期由SpringApplicationContext管理,設置為true則表示由ServletContainer管理 -->
	        <param-name>targetFilterLifecycle</param-name>
	        <param-value>true</param-value>
	    </init-param>
	</filter>
	<filter-mapping>
	    <filter-name>shiroFilter</filter-name>
	    <url-pattern>/*</url-pattern>
	</filter-mapping>

3.在application.xml(spring.xml)中配置Realm、安全管理器和shiro過濾器

 
        <!-- 配置自定義Realm -->
    <bean id="myRealm" class="com.oracle.shiro.UserRealm">
    	<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"/>
    </bean>

  <!-- Shiro過濾器 核心-->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- Shiro的核心安全接口,這個屬性是必須的 -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 身份認證失敗,則跳轉到登錄頁面的配置 -->
        <property name="loginUrl" value="/login.html"/>
        <property name="successUrl" value="/index.jsp"/>
        <!-- 權限認證失敗,則跳轉到指定頁面 -->
        <property name="unauthorizedUrl" value="/login.htmls"/>
        <!-- Shiro連接約束配置,即過濾鏈的定義 -->
        <property name="filterChainDefinitions">
            <value>
            	<!-- /candidate/admin/**=authc -->
                <!--anon 表示匿名訪問,不需要認證以及授權-->
				/login.htmls = anon
				/css/** = anon
				/dist/** = anon
				/js/** = anon
				/user/loginIn.dodo = anon
				/user/reg.dodo = anon
				/res/** = anon
				/logout = logout
                <!--authc表示需要認證 沒有進行身份認證是不能進行訪問的-->
                /**=authc
<!--            /student=roles[teacher]
                /teacher=perms["user:create"]
 -->            </value>
        </property>
    </bean>

4.新建一個UserRealm類,該類的路徑對應(3)中的自定義的Realm配置的class路徑。

package com.oracle.shiro;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

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.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationException;
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.util.StringUtils;

import com.oracle.model.User;
import com.oracle.service.RoleService;
import com.oracle.service.UserService;



public class UserRealm extends AuthorizingRealm {
   // 用戶對應的角色信息與權限信息都保存在數據庫中,通過UserService獲取數據
   @Resource
     private UserService userService;

    /**
     * 提供用戶信息返回權限信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    	String currentUsername = (String)super.getAvailablePrincipal(principals);
		List<String> roleList = null;  //用來存放角色碼的集合
		List<String> permissionList = null;  //用來存放當前用戶的權限碼
		//從數據庫中獲取當前登錄用戶的詳細信息
		User user = userService.findUserByUsername(currentUsername);
		if(null != user){
			permissionList = userService.getPermissions(user.getId());//根據當前登錄用戶的id,獲取當前用戶的權限碼
			roleList = userService.findRolesByUserId(user.getId());//根據當前用戶的id,獲取當前用戶的角色碼
		}else{
			throw new AuthorizationException();
		}
		//為當前用戶設置角色和權限
		SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();
		simpleAuthorInfo.addRoles(roleList);//把用戶角色碼交給shiro
		simpleAuthorInfo.addStringPermissions(permissionList);//把用戶權限碼交給shiro
		return simpleAuthorInfo;
    }

    /**
     * 提供賬戶信息返回認證信息
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
			String username = (String) token.getPrincipal();
			User user = userService.findUserByUsername(username);
			if (user == null) {
			    // 用戶名不存在拋出異常
			    throw new UnknownAccountException();
			}else{
				ByteSource salt = ByteSource.Util.bytes(user.getSalt());//鹽值
				SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getName(),
						user.getPassWord(),salt,getName());
				SecurityUtils.getSubject().getSession().setAttribute("CURRENT_USER", user);
				return authenticationInfo;
			}
			
    }
    
    
    
}

 注:在(4)中從數據庫中獲取用戶信息的方法,比較簡單,就不粘貼出來了(service->dao層->mapper.xml)

5.在spring-mvc.xml中配置,開啟shiro注解,shiro才能被正式使用。

 <!-- 開啟Shiro注解 -->
	     <!-- 保證實現了Shiro內部lifecycle函數的bean執行 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
	 
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/>
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>
    
    
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">  
    <property name="exceptionMappings">  
        <props>  
            <prop key="org.apache.shiro.authz.UnauthorizedException">
                /unauthorized
            </prop>  
        </props>  
    </property>  
    </bean>

 

 

 

 

登錄、注冊的controller中的代碼:

package com.oracle.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.oracle.model.User;
import com.oracle.service.UserService;

@Controller
@RequestMapping("/user")
public class UserController {
	private static Logger log = Logger.getLogger(UserController.class);
	@Autowired
	private UserService userServiceNew;
	
	@RequestMapping("/reg")
	@ResponseBody
	public Map reg(User user) {
		Map<String,Object> map = new HashMap<String,Object>();
//		user.setPassWord(JavaUtilMD5.MD5(user.getPassWord()));
		Random rd = new Random();
		int salt = rd.nextInt(100000);
		SimpleHash sh = new SimpleHash("MD5", user.getPassWord(),ByteSource.Util.bytes(salt+"") , 1024);
		user.setPassWord(sh.toString());
		user.setSalt(salt+"");
		int i = userServiceNew.save(user);
		if(i>0) {
			map.put("code", 200);
		}else {
			map.put("code", 500);
		}
		return map;
	}
	@RequestMapping("/loginIn")
	public String loginIn(User user,HttpSession session) {
		if(user == null) {//
			return "redirect:index.html?loginCode=500";
		}else {
			Subject subject = SecurityUtils.getSubject();
			// 判斷當前用戶是否登陸
			if (subject.isAuthenticated() == false) {
				UsernamePasswordToken token = new UsernamePasswordToken(user.getName(), user.getPassWord());
				try {
					subject.login(token);
//					Session session = subject.getSession();
				//	user = (SysUser) session.getAttribute(Constants.CURRENT_USER);
//					session.setAttribute("SESSION_USERNAME", user.getId() + "");
//					// 根據用戶id查找用戶角色
//					SysUser u = this.findUserByUserId(user.getId());
//					session.setAttribute("u", u);
					return "index";
				} catch (Exception e) {
					// 這里將異常打印關閉是因為如果登錄失敗的話會自動拋異常
					e.printStackTrace();
//					model.addAttribute("error", "用戶名或密碼錯誤");
					return "index";
				}
			} else {
//				Session session = getSession();
//				user = (SysUser) session.getAttribute(Constants.CURRENT_USER);
//				session.setAttribute("SESSION_USERNAME", user.getId() + "");
				return "index";
			}
		}
		
	}
	
	@Autowired
	HttpServletRequest request;
	@RequestMapping("/LoginInfo")
	@ResponseBody
	public Object Logininfo() {
		HttpSession httpSession=request.getSession();
		Object map=httpSession.getAttribute("CURR_USER");
		return map;		
	}
	
	@RequestMapping("/findPageData")
	@ResponseBody
	public Object findPageData(Integer page,Integer rows) {
		Integer startIndex = (page-1)*rows;
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("startIndex", startIndex);
		map.put("rows", rows);
		List<User> users = userServiceNew.findPageData(map);
		map.put("rows", users);
		map.put("total", userServiceNew.findTotleSize());
		return map;
	}
	@RequestMapping("/findAllUser")
	@ResponseBody
	public Object findAllUser() {
		return userServiceNew.findAllUser();
	}
	
	@RequestMapping("/user")
	public String user() {
		return "user";
	}
	
	@RequestMapping("/userSave")
	@ResponseBody
	public Map userSave(User user) {
		Map<String,Object> map = new HashMap<String,Object>();
		int i = userServiceNew.save(user);
		if(i>0) {
			map.put("code", 200);
		}else {
			map.put("code", 500);
		}
		return map;
	}
	
	@RequestMapping("/userUpdate")
	@ResponseBody
	public Map userUpdate(User user) {
		Map<String,Object> map = new HashMap<String,Object>();
		int i = userServiceNew.update(user);
		if(i>0) {
			map.put("code", 200);
		}else {
			map.put("code", 500);
		}
		return map;
	}
	
	@RequestMapping("/userDelete")
	@ResponseBody
	public Map userDelete(User user) {
		Map<String,Object> map = new HashMap<String,Object>();
		int i = userServiceNew.delete(user.getId());
		if(i>0) {
			map.put("code", 200);
		}else {
			map.put("code", 500);
		}
		return map;
	}
	
	@RequestMapping("/CurrUserMenu")
	@ResponseBody
	public Map<String,Object> findCurrUserMenu(){
		User user = (User)SecurityUtils.getSubject().getSession().getAttribute("CURRENT_USER");
		List<Map<String,Object>> menuList = userServiceNew.findCurrMenu(user.getId());
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("code", 100);
		map.put("msg", "");
		Map<String,Object> m = new HashMap<String,Object>();
		m.put("children", menuList);
		map.put("extend", m);
		return map;
	}
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM