• 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;
    	}
    }
    

      

  • 相关阅读:
    彻底弄懂GMT、UTC、时区和夏令时
    揭秘webpack loader
    揭秘webpack plugin
    封装axios
    webpack优化之玩转代码分割和公共代码提取
    node.js操作数据库之MongoDB+mongoose篇
    GitHub项目徽标
    Java中容易遗漏的小知识点( 一 )(为了和小白一样马上要考试的兄弟准备的,希望小白和大家高过不挂)
    QNX Message Passing,一个让人头秃的 IPC BUG
    【百面】02_模型评估
  • 原文地址:https://www.cnblogs.com/WQX-work24/p/10143290.html
Copyright © 2020-2023  润新知