`

shiro 概念总结

 
阅读更多

shiro 流程大概总结:

 

JSP:

配置loginUrl,在此URL返回的视图里,会有个form(此form无须指明action,我想是因为配置了loginUrl的关系,但是配置了authc 为loginUrl),提交后,就会进入FormAuthenticationFilter,你可以重写他,处理自己的逻辑,如写response为JSON的,等等。这样如果登陆成功了,会根据之前访问的URL,和配置的SUCCEEURL作为备选,优先是去之前的URL,(有个疑问,如果之前的是login,那现在登陆成功后还是login?或者处理了下如果是login就返回备选URL,如果没有配successUrl呢,是不是应该有什么必须的东西再里面)。这样就访问到之前的URL了,一般都是/,就是首页了,controller里面定义下这个这个返回方法就行(可以写个mainController,用来处理首页的。有时候还可以把 / 配置成重定向到另外一个controler,不提了)

 

JSON:

 

上面都是JSP的,不适合EXT,同样需要配置loginUrl,登陆操作不是用form来了,用ajax提交的,同样配置了authc 为loginUrl,同样进FormAuthenticationFilter,这时候肯定要重新它了,让它返回JSON,自己在JS sucess里面回调重定向到首页(wecome/index/home 这种名字的)。

 

 

还有个注意的,所谓的shiro权限字符串(如 "admin:session:forceLogout"),这玩意没什么特别的地方,就是一个ID,一个有意义的ID,我之前一直以为shiro会怎么处理它,发现就是ID而已,甚至可以用 其他什么ID来代替它,这玩意就是用来唯一标识一个权限的。一般可以在controller里面方法上面 加入注解 @RequiresPermissions("admin:session:forceLogout")(也可以在页面上用shiro 标签 包裹某段代码,用以实现该段代码是否显示)。

 

(上面这段错了,还是有意义的,shiro会用通配符来匹配,两边进行equals,

 

 @Override  
    public boolean implies(Permission p) {  
        if(!(p instanceof BitPermission)) {  
            return false;  
        }  
        BitPermission other = (BitPermission) p;  
        if(!("*".equals(this.resourceIdentify) || this.resourceIdentify.equals(other.resourceIdentify))) {  
            return false;  
        }  
        if(!(this.permissionBit ==0 || (this.permissionBit & other.permissionBit) != 0)) {  
            return false;  
        }  
        if(!("*".equals(this.instanceId) || this.instanceId.equals(other.instanceId))) {  
            return false;  
        }  
        return true;  
    }  

 ,只有当是通配符,或者相等时候,返回 TRUE),就是分解,然后三个部分进行相等比较,三个部分表示



 

 

在spring-mvc配置文件里统一处理异常

 <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">  
         <property name="exceptionMappings">  
             <props>  
                 <prop key="java.lang.Exception">error/500</prop>  
                 <prop key="java.lang.RuntimeException">error/500</prop>  
                 <prop key="java.lang.Throwable">error/500</prop>  
                 <prop key="UnauthorizedException">error/noRealm</prop>  
             </props>  
         </property>    
         <!-- 设置日志输出级别,不定义则默认不输出警告等错误日志信息 -->  
         <property name="warnLogCategory" value="WARN"></property>  
         <!-- 默认错误页面,当找不到上面mappings中指定的异常对应视图时,使用本默认配置 -->  
         <property name="defaultErrorView" value="error/500"></property>  
         <!-- 默认HTTP状态码 -->  
         <property name="defaultStatusCode" value="500"></property>  
     </bean>  

 

 

这里可能JSON的就不是这么处理了。(如果权限粒度只到菜单 这个返回页面的 ,不到操作按钮的这种AJAX 返回JSON的,是可以满足的)。

 

 

 

 

总结,主要还是AuthorizingRealm这个类,和FormAuthenticationFilter这个类

 

public class ShiroDbRealm extends AuthorizingRealm {
	
	private static Logger logger = LoggerFactory.getLogger(ShiroDbRealm.class);
	
	
	@Autowired
	protected AccountService accountService;

	/**
	 * 认证回调函数,登录时调用.
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
		logger.info("doGetAuthenticationInfo----");
		
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		User user = null;
		try {
			user = accountService.findUserByLoginName(token.getUsername());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if (user != null) {
			
			byte[] salt = Encodes.decodeHex(user.getSalt());//16进制的
			return new SimpleAuthenticationInfo(user,
					user.getPassword(), ByteSource.Util.bytes(salt), getName());
			
//			return new SimpleAuthenticationInfo();
		} else {
			return null;
		}
	}
	
	/**
	 * 设定Password校验的Hash算法与迭代次数.
	 */
	@PostConstruct
	public void initCredentialsMatcher() {
		HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(AccountService.HASH_ALGORITHM);
		matcher.setHashIterations(AccountService.HASH_INTERATIONS);
		setCredentialsMatcher(matcher);
		
	}
	
	

	/**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = (String)principals.getPrimaryPrincipal();
        //Authorization 授权,即权限验证,验证某个已认证的用户是否拥有某个权限
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		try {
			User user = this.userService.getUserByName(username);
	        Set<String> roles = new HashSet<String>();
	        //本系统设计为一个用户属于一个用户组,即用户组就是用户的角色(employee、finance、hr、boss..);每个用户组有不同的权限(资源)
	        //其他系统中可以设置 一个用户有多个角色,一个角色有多个权限
	        //在本系统中 除了管理员是admin其他组都用user标识,除了老板,其他用户组的操作都和员工组一样的。
	        roles.add("admin".equals(user.getGroup().getType())?"admin":"user");
	        
	        List<GroupAndResource> grList = this.grService.getResource(user.getGroup().getId());
	        Set<String> resources = new HashSet<String>();
	        for(GroupAndResource gr : grList){
	        	Resource resource = this.resourceService.getPermissions(gr.getResourceId());
	        	if(!BeanUtils.isBlank(resource)){
	        		resources.add(resource.getPermission());
	        	}
	        }
	        
	        authorizationInfo.setRoles(roles);
	        authorizationInfo.setStringPermissions(resources);
	        
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.error("realm 错误!");
		}
		return authorizationInfo;
    }


	public void setAccountService(AccountService accountService) {
		this.accountService = accountService;
	}

 

 

public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {  
	private static final Logger log = LoggerFactory
			.getLogger(CustomFormAuthenticationFilter.class);
	
	 /** 
     * 所有请求都会经过的方法。 
     */  
    @Override  
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {  
    	 if (isLoginRequest(request, response)) {  
             if (isLoginSubmission(request, response)) {  
                 if (log.isTraceEnabled()) {  
                     log.trace("Login submission detected.  Attempting to execute login.");  
                 }  
                 //验证码暂不处理
//                 if ("XMLHttpRequest"  
//                         .equalsIgnoreCase(((HttpServletRequest) request)  
//                                 .getHeader("X-Requested-With"))) {// 不是ajax请求  
//                     String vcode = request.getParameter("vcode");  
//                     HttpServletRequest httpservletrequest = (HttpServletRequest) request;  
//                     String vvcode = (String) httpservletrequest  
//                             .getSession()  
//                             .getAttribute("com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY"  
//                                     );  
//                     if (vvcode == null || "".equals(vvcode)  
//                             || !vvcode.equals(vcode)) {  
//                         response.setCharacterEncoding("UTF-8");  
//                         PrintWriter out = response.getWriter();  
//                         out.println("{success:false,msg:'验证码错误'}");  
//                         out.flush();  
//                         out.close();  
//                         return false;  
//                     }  
//                 }  
                 return executeLogin(request, response);  
             } else {  
                 if (log.isTraceEnabled()) {  
                     log.trace("Login page view.");  
                 }  
                 // allow them to see the login page ;)  
                 return true;  
             }  
         } else {  
             if (log.isTraceEnabled()) {  
                 log.trace("Attempting to access a path which requires authentication.  Forwarding to the "  
                         + "Authentication url [" + getLoginUrl() + "]");  
             }  
             if (!"XMLHttpRequest"  
                     .equalsIgnoreCase(((HttpServletRequest) request)  
                             .getHeader("X-Requested-With"))) {// 不是ajax请求  
                 saveRequestAndRedirectToLogin(request, response);  
             } else {  
                 response.setCharacterEncoding("UTF-8");  
                 PrintWriter out = response.getWriter();  
                 out.println("{msg:'login'}");  
                 out.flush();  
                 out.close();  
             }  
             return false;  
         }
    }  
    
    /**
     * 覆盖默认实现,用sendRedirect直接跳出框架,以免造成js框架重复加载js出错。
     * @param token
     * @param subject
     * @param request
     * @param response
     * @return
     * @throws Exception  
     * @see org.apache.shiro.web.filter.authc.FormAuthenticationFilter#onLoginSuccess(org.apache.shiro.authc.AuthenticationToken, org.apache.shiro.subject.Subject, javax.servlet.ServletRequest, javax.servlet.ServletResponse)
     */
    @Override
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject,
            ServletRequest request, ServletResponse response) throws Exception {
        //issueSuccessRedirect(request, response);
        //we handled the success redirect directly, prevent the chain from continuing:
        HttpServletRequest httpServletRequest = (HttpServletRequest)request;
        HttpServletResponse httpServletResponse = (HttpServletResponse)response;
         
        if (!"XMLHttpRequest".equalsIgnoreCase(httpServletRequest.getHeader("X-Requested-With")) 
                && request.getParameter("ajax") == null) {// 不是ajax请求 让他重定向到页面
        	issueSuccessRedirect(request, response);
        } else {//在ajax里面,用不了shiro配置的successurl重定向功能,只能在回调函数里重定向     wj 2016-9-7
        	httpServletResponse.setCharacterEncoding("UTF-8");
			PrintWriter out = httpServletResponse.getWriter();
			out.println("{success:true,msg:'登入成功'}");
			out.flush();
			out.close();
        }
         
        return false;
    }
    
    
    /** 
     * 主要是处理登入失败的方法 
     */  
    @Override  
    protected boolean onLoginFailure(AuthenticationToken token,  
            AuthenticationException e, ServletRequest request,  
            ServletResponse response) {  
        if (!"XMLHttpRequest".equalsIgnoreCase(((HttpServletRequest) request)  
                .getHeader("X-Requested-With"))) {// 不是ajax请求  
            setFailureAttribute(request, e);  
            return true;  
        }  
        try {  
            response.setCharacterEncoding("UTF-8");  
            PrintWriter out = response.getWriter();  
            String msg = e.getClass().getSimpleName();  
            if ("IncorrectCredentialsException".equals(msg)) {  
                out.println("{success:false,msg:'密码错误'}");  
            } else if ("UnknownAccountException".equals(msg)) {  
                out.println("{success:false,msg:'账号不存在'}");  
            } else if ("LockedAccountException".equals(msg)) {  
                out.println("{success:false,msg:'账号被锁定'}");  
            } else {  
                out.println("{success:false,msg:'未知错误'}");  
            }  
            out.flush();  
            out.close();  
        } catch (IOException e1) {  
            // TODO Auto-generated catch block  
            e1.printStackTrace();  
        }  
        return false;  
    }  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


  • 大小: 47.8 KB
0
0
分享到:
评论

相关推荐

    权限管理shiro学习总结

    【权限管理框架Shiro学习总结】 在IT领域,权限管理是一个关键的安全机制,它确保了只有合法的用户才能访问特定的资源。Apache Shiro是一个强大且易用的Java安全框架,提供认证、授权、会话管理和加密等功能。下面...

    shiro 个人总结

    本总结将从 Shiro 的基本概念、验证和授权过程、加密方式和 JSP 标签等方面进行总结。 一、基本概念 1. Subject(主体):当前操作的用户。 2. SecurityManager(安全管理器):负责管理安全相关的操作,包含 ...

    吴天雄--shiro个人总结笔记.doc

    Apache Shiro 是一款Java安全框架,它提供了身份认证、授权、加密和会话...对于面试和学习来说,掌握Shiro的基本概念、架构以及核心功能,可以帮助开发者构建安全的Java应用,并且在面试时展现出扎实的安全管理知识。

    shiro学习心得

    通过本文档,将深入探讨 Shiro 的核心概念,并结合实际应用场景来理解其工作原理。 ##### 1.1 认证(Authentication) 认证是验证用户身份的过程,通常基于用户名和密码。在 Shiro 中,认证可以通过以下步骤完成:...

    shiro权限案例demo

    1. **Subject**:是Shiro的中心概念,代表了当前“安全的用户”。它提供了进行认证、授权、会话管理和事件监听的主要接口。 2. **Realms**: Realm是Shiro与应用安全数据源(如数据库)的桥梁,它负责验证凭证并...

    Shiro_学习总结.zip

    这个“Shiro_学习总结.zip”文件包含了一个 PDF 文档,很可能是对 Shiro 框架核心概念、功能以及使用方法的详尽总结。 在 Shiro 中,主要涉及以下几个核心组件: 1. **认证(Authentication)**:这是验证用户身份...

    shiro_attack_2.2.zip

    下面我们将深入探讨Apache Shiro的基本概念、常见攻击以及如何防范这些攻击。 **Apache Shiro框架** Apache Shiro的核心组件包括认证、授权、会话管理和加密。认证是验证用户身份的过程,授权则涉及决定用户是否有...

    struts2和shiro完美整合解决方案

    总结一下,Struts2和Shiro的整合提供了完整的Web应用安全解决方案,包括用户认证、授权、会话管理和权限控制。通过合理配置和使用,开发者可以构建出安全、易用的Java Web应用。提供的压缩包"shirodemo"应包含了一个...

    Shiro-pdf教程

    通过这个教程,你可以了解到Shiro的基本概念和API,为后续更深入的学习打下基础。 总结来说,Apache Shiro 是一个全面的安全框架,能够满足各种类型应用程序的安全需求,提供简洁的API来处理复杂的安全问题。无论是...

    springboot+shiro入门案例

    **Shiro框架核心概念** 1. **身份验证(Authentication)**:验证用户身份的过程,即确定用户是谁。 2. **授权(Authorization)**:也称为访问控制,决定用户是否有权限执行特定的操作或访问特定资源。 3. **会话...

    shiro入门学习.ppt

    总结一下,Shiro的核心组件包括: 1. Subject:代表用户。 2. SecurityManager:是Shiro的核心,协调各组件工作。 3. Authenticator:处理用户登录验证。 4. Authorizer:决定用户的角色和权限。 5. SessionManager...

    Shiro入门实例

    Shiro 的核心概念包括主体(Subject)、安全管理者(SecurityManager)、身份验证(Authentication)、授权(Authorization)以及会话管理(Session Management)。 - **主体(Subject)**:代表当前用户,可以是...

    shiro框架教案+笔记+sql脚本+项目案例

    首先,"shiro框架教案"部分可能涵盖了Shiro的基本概念、架构设计、核心组件如Subject、Realms、Caches等的讲解,以及如何配置和使用Shiro进行用户认证和权限授权。教案通常会以教学步骤的形式,逐步解析Shiro的工作...

    ssm+shiro权限框架

    1. Shiro通过Role(角色)和Permission(权限)的概念来进行授权。角色是一组权限的集合,权限则是对特定资源的操作。 2. 在系统初始化时,将用户的角色和权限加载到内存。 3. 当用户尝试访问资源时,Shiro会检查...

    shiro权限管理实例

    总结起来,"shiro权限管理实例"为我们提供了一个学习Shiro权限控制的实践平台。通过这个实例,我们可以了解如何设置身份验证、授权、会话管理和加密,这对于任何需要用户权限管理的Java应用都是非常有价值的。

    shiro认证授权

    Apache Shiro 是一个...总结,Apache Shiro 是一个功能丰富的安全框架,能够轻松处理认证、授权、加密和会话管理。通过对 `shiro-demo` 项目的理解和实践,你将能掌握 Shiro 的基本用法,并能在实际项目中有效运用。

    shiro视频教程-最全,通俗易懂

    通过上述知识点的学习,Java开发者及相关专业和技术爱好者将能够深入理解Shiro框架的核心概念与工作原理,并能够运用到实际项目开发中,实现用户认证、授权、加密等功能,从而提升项目的整体安全性和用户体验。

    shiro视频教程

    本教程旨在全面介绍 Apache Shiro 的基础知识和实践技巧,帮助开发者快速掌握 Shiro 的核心概念和技术细节,为实际项目中的安全控制提供坚实的基础。通过深入理解 Shiro 的架构和工作原理,开发者能够更加灵活地运用...

    在web项目中应用Shiro

    Realm是Shiro框架中的核心概念之一,它是Shiro与应用数据源之间的桥梁,负责加载用户信息、角色和权限。常见的实现方式包括JDBCRealm,适用于使用关系数据库的应用程序。此外还有CASRealm等其他类型的Realm,用于...

Global site tag (gtag.js) - Google Analytics