shiro权限框架中的认证和授权过程


        
         
        
        
            
                
            
        
        
            
            	
            	/images/** = anon
            	/js/** = anon
            	/styles/** = anon
            	
                /logout = logout
                /** = authc
            
        
    

首先看一下Shiro中的web filter过滤器:

         默认采用的认证过滤器filter是表单过滤器,默认登录的url是/login(只要没有认证的都会跳转到/login路径下),辅助登录成功url是/first。


默认登录url跳转到的页面是login.jsp如下:


<%@ page contentType="text/html; charset=UTF-8"%>
<%@ include file="/WEB-INF/jsp/tag.jsp"%>


药品采购平台










<%@ include file="/WEB-INF/jsp/common_js.jsp"%>




	
<%-- --%>
用户名:
密 码:
验证码: 刷新

form过滤器有个特点就是,只要是表单提交(条件:1.post   2.action路径为"")就相当于:

Subject currentUser = SecurityUtils.getSubject();
currentUser.login(token);

他会自动到Real中的方法进行身份认证:

/**
	 * 身份认证
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		String userName = (String) token.getPrincipal();
		User user = userService.findByUsername(userName);
		
		if(user == null) {
			//抛出用户不存在异常
			throw new UnknownAccountException();//没找到帐号
		}
		if(user.getLocked()) {
			//抛出用户被锁定异常
			throw new LockedAccountException(); //帐号锁定
		}
		// 如果查询到返回认证信息AuthenticationInfo
		SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userName, user.getPassword(),ByteSource.Util.bytes(user.getCredentialsSalt()),
				this.getName());

		return simpleAuthenticationInfo;
	}

值得注意的是SimpleAuthenticationInfo这个方法的构造函数,因为它决定了凭证认证的方式:

1.

   public SimpleAuthenticationInfo(Object principal, Object credentials, String realmName) {
        this.principals = new SimplePrincipalCollection(principal, realmName);
        this.credentials = credentials;
    }

该构造器对应的默认任凭类,什么都不需要输入,没有加密算法,没有迭代次数,直接通过用户名和密码进行进行验证就可以。


    	
    	
    


2.

  public SimpleAuthenticationInfo(Object principal, Object hashedCredentials, ByteSource credentialsSalt, String realmName) {
        this.principals = new SimplePrincipalCollection(principal, realmName);
        this.credentials = hashedCredentials;
        this.credentialsSalt = credentialsSalt;
    }

这个和你加密的密码salt有关:

package com.lgy.service;

import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.lgy.model.User;
	
@Service
public class PasswordHelper {
    private RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();

    @Value("${password.algorithmName}")
    private String algorithmName;
    @Value("${password.hashIterations}")
    private int hashIterations;

    public void encryptPassword(User user) {

        user.setSalt(randomNumberGenerator.nextBytes().toHex());

        String newPassword = new SimpleHash(
                algorithmName,           //加密算法
                user.getPassword(),      //密码
                ByteSource.Util.bytes(user.getCredentialsSalt()),  //salt盐   username + salt
                hashIterations   //迭代次数
                ).toHex();

        user.setPassword(newPassword);
    }
}

所以需要设置凭证信息:


    
    	
    	
    
     
    
    
    	
    	
    	
    	
       

若认证通过后,它会跳转到设置的辅助登录成功url是/first。身份认证就到这里结束!


授权过程如下:

shiro授权有三种方式

Shiro 支持三种方式的授权:

1 编程式:通过写if/else 授权代码块完成:

Subject subject =SecurityUtils.getSubject();

if(subject.hasRole(“admin”)) {

//有权限

} else {

//无权限

}

2 注解式:通过在执行的Java方法上放置相应的注解完成:

@RequiresRoles("admin")

public void hello() {

//有权限

}

3.JSP/GSP 标签:在JSP/GSP 页面通过相应的标签完成:


编程试的不用说了,重点说说注解方式和jsp标签方式:

若使用SpringMVC注解试,需要在SpringMVC的配置文件中配置注解启动:




    
    
        
    

在控制器中:

    @RequiresPermissions("user:create")
    @RequestMapping(value = "/create", method = RequestMethod.GET)
    public String showCreateForm(Model model) {
        //...
        return "user/edit";
    }
当进入到这个Controller中的时候,会先进入realm中的:

/**
	 * 授权认证
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		User user = (User) principals.getPrimaryPrincipal();
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setRoles(userService.findRoles(user.getUsername()));
        authorizationInfo.setStringPermissions(userService.findPermissions(user.getUsername()));
		return authorizationInfo;
	}

         权限比较可能有如下2个:

 @RequiresPermissions("user:create")
 @RequiresRoles("admin")

1.基于角色的认证

2.基于权限码的认证


若使用jsp标签进行认证:

条件:需要导入<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

页面中

......


    

      ......
 


同上进入该页面中时候,若出现这样的标签,每出现一个都会调用realm中的:

/**
	 * 授权认证
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		User user = (User) principals.getPrimaryPrincipal();
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setRoles(userService.findRoles(user.getUsername()));
        authorizationInfo.setStringPermissions(userService.findPermissions(user.getUsername()));
		return authorizationInfo;
	}


相当于他们调用了shiro中的:

                Subject subject = SecurityUtils.getSubject();
subject.checkRole("");
subject.checkPermission("");                 


*

shiro的jsp标签

 

Jsp页面添加:

<%@ tagliburi="http://shiro.apache.org/tags"prefix="shiro" %>

 

标签名称

标签条件(均是显示标签内容)

登录之后

不在登录状态时

用户在没有RememberMe时

用户在RememberMe时

在有abc或者123角色时

拥有角色abc

没有角色abc

拥有权限资源abc

没有abc权限资源

显示用户身份名称

      显示用户身份中的属性值

  当然每次这么做可能浪费的性能很不好,需要配置缓存。

你可能感兴趣的:(权限框架)