shiro的学习

先在pom文件里导入shiro的jar,这个例子shiro的版本用的是<shiro.version>1.2.2</shiro.version> ,使用@RequiresPermissions等注解,一定要加spring aop的包和org.aspectj.aspectjweaver的jar。

<!-- 导入shiro核心包 -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		<!-- 导入shiro-spring支持 -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		<!-- 导入shiro-web支持 -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-web</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		<!-- 导入shiro-EHCache支持 -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-ehcache</artifactId>
			<version>1.2.2</version>
		</dependency>

然后创建一个sprin-shiro的文件:

<?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:p="http://www.springframework.org/schema/p"
	xmlns:tx="http://www.springframework.org/schema/tx" 
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
		http://www.springframework.org/schema/util
		http://www.springframework.org/schema/util/spring-util-4.3.xsd
		http://www.springframework.org/schema/mvc
		http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">
                     
    
      <!--定义cookie的属性  -->
      <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
       <constructor-arg value="rememberMe" />
       <property name="httpOnly" value="true" />
       <!-- 默认记住7天(单位:秒) -->
       <property name="maxAge" value="604800" />
   </bean>
   <!-- rememberMe管理器  (org.apache.shiro.codec.Base64).decode('')里面的key可以随意更改
                    生成方法 在AbstractRememberMeManager类里:
       AesCipherService aes = new AesCipherService();
       byte[] key = aes.generateNewKey().getEncoded();
       String base64 = Base64.encodeToString(key);
   -->
   <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
    <property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('MPdCMZ9urzEA50JDlDYYDg==')}" />
       <property name="cookie" ref="rememberMeCookie" />
   </bean>
    <!--自定义的拦截器  -->
    <bean id="remeberFilter" class="com.glodio.shiro.RemeberFilter" />
    <!-- shiro配置 用于验证信息和权限 -->
    <bean id="realm" class="com.glodio.shiro.ShiroDBRealm" >
    <!--密码匹配  --> 
    <property name="credentialsMatcher">
            <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                 <!--调用什么加密方法  -->
                 <property name="hashAlgorithmName" value="MD5"></property> 
                  <!--调用什么加密几次  -->
                 <property name="hashIterations" value="1"></property>
            </bean>
        </property>        
    </bean>
    
    <!--配置 securityManager -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
	        <property name="realm" ref="realm" />   
	        <property name="rememberMeManager" ref="rememberMeManager" />     	   		
	</bean>
	
	
    <!--shiroFilter这个名字 一定要和web.xml的名字一样  -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">		    	
	    <!-- Shiro的核心安全接口,这个属性是必须的 -->
	    <property name="securityManager" ref="securityManager"/>
	    <!--登录的url 如果没有登录 就会跳转到该页面  --> 
	    <property name="loginUrl" value="/"/>
	    <!--没权限的url  -->
	    <property name="unauthorizedUrl" value="/"/>
	    <!--配置自己的过滤器  -->
	    <property name="filters">
	       <util:map>
              <entry key="remeberFilter" value-ref="remeberFilter"></entry>
           </util:map>  
	    </property>
	    <!--验证规则 只有要一个符合 下面的就不会执行 所以匿名访问的要写在前面  -->
	    <property name="filterChainDefinitions">
	        <value>
	        	/ = anon
	        	/login.html = anon
	            /system/login = anon
	            /logout = anon
	            /src/** = anon
	            /public/** = anon
	          	/** = remeberFilter
	        </value>
	    </property>
	</bean>
	
	
	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
  
</beans>

如果要加 @RequiresPermissions 等注解 ,必须在spring mvc的注解里添加:

 <aop:config proxy-target-class="true"/>
      <!--在controller层加注解:使用shiro时必须添加的配置--> 
     <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor">
           <property name="proxyTargetClass" value="true"/> 
     </bean>      
     <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>

在web.xml文件里加shiro的过滤器

<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <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>

 

RemeberFilter类:

import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.springframework.beans.factory.annotation.Autowired;
import com.glodio.bean.Role;
import com.glodio.bean.Url;
import com.glodio.bean.User;
import com.glodio.bean.UserInf;
import com.glodio.service.IRoleService;
import com.glodio.service.IUserService;
import com.glodio.service.UrlService;
import com.glodio.util.StringUtil;

public class RemeberFilter extends AccessControlFilter{

    

    @Autowired
    private UrlService urlService;

    @Resource
    private IRoleService iRoleService;
    
    @Resource
    IUserService iUserService;

    
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
            throws Exception {
        boolean result = false;
        Subject subject = SecurityUtils.getSubject();
        //这个session 就是httpSession 在web容器下 shiro的session 就是httpSession
        Session session = subject.getSession();
        //如果登录直接返回true
        if(subject.isAuthenticated()){
            return true;
        }
        //如果是记住 没有登录 那么需要初始化session中的用户信息
        if(subject.isRemembered() && !subject.isAuthenticated()){
            result = true;
            User user = (User)session.getAttribute("user");
            if(user == null){
                String userName = (String) subject.getPrincipal();
                user = iUserService.queryBean(userName);
                if(user != null){
                    session.setAttribute("user", user);
                    initRoles(user,session);
                }
            }
            
            
        }
        
        return result;
    }
    
    //如果被拒绝 那么直接返回到登录页
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        
        redirectToLogin(request, response);
        return false;
    }

    

  
    private void initRoles(User bean, Session session) {
        if (StringUtil.strIsNullOrEmpty(bean.getRolename())) {
           
            return;
        }
        Role role = iRoleService.selectByRoleName(bean.getRolename());
        if (role == null || StringUtil.strIsNullOrEmpty(role.getUrlremark())) {
            
            return;
        }
        String[] ulrIds = role.getUrlremark().split(";");
        if (ulrIds == null || ulrIds.length == 0) {
            return;
        }
        List<Integer> ids = new ArrayList<>();
        for (String id : ulrIds) {
            ids.add(Integer.parseInt(id));
        }
        List<String> permissions = new ArrayList<>();
        List<Url> urls = urlService.selectListByIds(ids);
        if (urls != null) {
            session.setAttribute("urls", urls);
            for(Url url : urls){
                permissions.add(url.getUrlAddr());
            }
            
        }
        UserInf userInf = new UserInf();
        userInf.setUsr(bean);
        userInf.setPermissions(permissions);
        session.setAttribute(UserInf.USERINF, userInf);  
    }
    
    

}

ShiroDBRealm类:

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.authc.UsernamePasswordToken;
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.util.ByteSource;

import com.glodio.bean.User;
import com.glodio.bean.UserInf;
import com.glodio.service.IUserService;

public class ShiroDBRealm extends AuthorizingRealm {
	
	@Resource
	private IUserService iUserService;
	

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
		Session session = SecurityUtils.getSubject().getSession();
		UserInf userInf  = (UserInf) session.getAttribute(UserInf.USERINF);
		SimpleAuthorizationInfo authorizationInfo = null;
		if(userInf != null){
		    authorizationInfo = new SimpleAuthorizationInfo();
		    authorizationInfo.addStringPermissions(userInf.getPermissions());
		  
		}
		return authorizationInfo;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
        // 把token转换成User对象  
	    UsernamePasswordToken upt = (UsernamePasswordToken)authcToken;
	    String username = upt.getUsername();
	    String password = String.valueOf(upt.getPassword());
	    User userLogin = tokenToUser(upt);
        // 根据验证用户名查找用户   这里可以根据用户状态 抛出多个异常 然后在login方法里进行捕捉
	    User u = iUserService.queryBeanPassword(username);
        if(u == null) {
            throw new UnknownAccountException("用户不存在");
        }
        //当前 Realm 的 name  
        String realmName = this.getName();  
        //principal 就是用户名
        Object principal = upt.getPrincipal();
        ByteSource salt = ByteSource.Util.bytes(username);
        //会验证密码是否匹配
        return new SimpleAuthenticationInfo(principal, u.getPassword(), salt,realmName);  
	}
	
    private User tokenToUser(UsernamePasswordToken authcToken) {  
        User user = new User();  
        user.setUsername(authcToken.getUsername());  
        user.setPassword(String.valueOf(authcToken.getPassword()));  
        return user;  
    }

}

login方法:

@ResponseBody
    @RequestMapping("/login")
    public Map<String, Object> login(HttpServletRequest request, @Param("username") String username,
            @Param("password") String password) throws Exception {
        Map<String, Object> dataMap = new HashMap<>();
        boolean result = false;
        User bean = iUserService.queryBeanPassword(username);
        Subject subject = SecurityUtils.getSubject();
        
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
        //捕捉登录出现的异常
        try {
           //是否记住用户名,shiro 在cookie里面只存了用户名
            usernamePasswordToken.setRememberMe(true);
            subject.login(usernamePasswordToken);
            if(subject.isAuthenticated()){
                result = true;
            }
            // if no exception, that's it, we're done!
        } catch (UnknownAccountException uae) {
            // username wasn't in the system, show them an error message?
            result = false;
            dataMap.put("msg", "当前用户名不存在!");
        } catch (IncorrectCredentialsException ice) {
            dataMap.put("msg", "用户名或密码错误!");
        } catch (LockedAccountException lae) {
            // account for that username is locked - can't login. Show them a
            // message?

        } catch (AuthenticationException ae) {
            ae.printStackTrace();
            dataMap.put("msg", "系统出错,请稍后重试!");
        }
        if (result) {
            if (bean != null ) {
                result = true;
                request.getSession().setAttribute("user", bean);
                // String rolename = bean.getRolename();
                initRoles(bean, request.getSession());

            }
        }
        dataMap.put("result", result);
        return dataMap;

    }

权限验证:在controller 里面的方法 加@RequiresPermissions等注解就行。如果没有这个权限,会抛出异常 ,所有必须捕获这个异常

@RequiresPermissions("src/org.html")
	@RequestMapping("/OrgList")
	public @ResponseBody Map<String, Object> OrgList(HttpServletRequest request) throws Exception{
		Map<String, Object> dataMap = new HashMap<>();
		Map<String, Object> map = new HashMap<String, Object>();
		ArrayList<Org> list = null;
		int total = 0;
		
		int pageNumber = Integer.parseInt(request.getParameter("pageNumber"));
		int pageSize = Integer.parseInt(request.getParameter("pageSize"));
		
		if(pageNumber > 0) {
			pageNumber = (pageNumber-1)*pageSize;
		}
		else {
			pageNumber = 0;
		}
		
		map.put("pageNumber", pageNumber);
		map.put("pageSize", pageSize);
		
		// 获取当前用户bean,取得用户所在机构,根据所在机构获取用户所有机构权限,再根据所有机构的显示数据信息
		User user = (User)request.getSession().getAttribute("user");
		List<Integer> orgIdList = iOrgService.getOrgIdCollection(user.getOrgId());
		map.put("list", orgIdList);

		total = iOrgService.queryAllCountForOrgId(orgIdList);
		if(total > 0) {
			list = iOrgService.queryBeansForOrgId(map);
		}
		total = (total+pageSize)/pageSize;
		dataMap.put("total", total);
		dataMap.put("list", list);
		
		return dataMap;
	}

CustomExceptionResolver类:简单的捕获了AuthorizationException异常

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import org.apache.shiro.authz.AuthorizationException;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
@Component
public class CustomExceptionResolver implements HandlerExceptionResolver{

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
            Exception ex) {
        ex.printStackTrace();
        //对异常类型进行判断
        if(ex instanceof AuthorizationException){
            response.setCharacterEncoding("utf-8");
            PrintWriter writer = null;
            try {
                writer = response.getWriter();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            writer.println("没有该权限!");
            writer.close();
            return null;
        }else{
            return new ModelAndView();
        }
         
    }
}

 

Filter Name                     Class
anon                  org.apache.shiro.web.filter.authc.AnonymousFilter
authc                   org.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasic         org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
logout                  org.apache.shiro.web.filter.authc.LogoutFilter
noSessionCreation  org.apache.shiro.web.filter.session.NoSessionCreationFilter
perms                  org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
port                            org.apache.shiro.web.filter.authz.PortFilter
rest                          org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
roles                          org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
ssl                          org.apache.shiro.web.filter.authz.SslFilter
user                          org.apache.shiro.web.filter.authc.UserFilter

这个可以看出每个过滤器名称都有一个过滤器类,所以

 <property name="filterChainDefinitions">
            <value>
                / = anon
                /login.html = anon
                /system/login = anon
                /logout = anon
                /src/** = anon
                /public/** = anon
                  /** = remeberFilter
            </value>
        </property>

我们自己可以定义一些过滤器来控制访问的权限 或 做一些其他事

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值