springMVC与shiro集成

 

shiro可以跟springMVC很好的集成。

但是对于shiro集成struts2的资料比较少。

容易遇到注解失效等问题。

因为很多老的项目可能用的是Spring+ sturts框架。

如果我们使用shiro跟sturts集成的话 需要用到sturts的注解。

这样其实struts也失去了它跳转配置的便利。

所以  考虑了之后  还是觉得 使用springMVC框架与shiro集成。

 

 

我现在有一个spirngMVC的框架,在此基础上进行shiro的添加测试。

 

权限分析

用户分为两种用户normal,manager,有五个模块:结果查看模块,用户数据生成单选模块,用户数据生成批量模块,用户权限管理模块,操作日志查看模块。

normal用户:

结果查看模块resultlist,

用户数据生成单选模块parseResultUserlist,parseResultAdd

用户数据生成批量模块parseResultUserlistMulti,parseResultAddMulti

manager用户:

结果查看模块resultlist,

用户数据生成单选模块parseResultUserlist,parseResultAdd

用户数据生成批量模块parseResultUserlistMulti,parseResultAddMulti

用户权限管理模块usermanage,

操作日志查看模块。loglist

 

新建User.class

根据shiro的模型 我们需要给User加上角色role和权限permission。因为我用的mongodb数据库是非关系型的数据库。我们把role和permission直接加在User对象里。

User.java

 

package com.test.domain.entity;


import java.util.List;


public class User {
	private String id;
	private String username;
	private String password;
	private List permissionList;//一个角色对应多个权限  
	private List roleList;//一个用户具有多个角色
	private List otherContacts;// 其他联系人
	
	public String getUsername() {
		return username;
	}


	public void setUsername(String username) {
		this.username = username;
	}


	public String getPassword() {
		return password;
	}


	public void setPassword(String password) {
		this.password = password;
	}


	public String getId() {
		return id;
	}


	public void setId(String id) {
		this.id = id;
	}


	public List getPermissionList() {
		return permissionList;
	}


	public void setPermissionList(List permissionList) {
		this.permissionList = permissionList;
	}


	public List getRoleList() {
		return roleList;
	}


	public void setRoleList(List roleList) {
		this.roleList = roleList;
	}


	public List getOtherContacts() {
		return otherContacts;
	}


	public void setOtherContacts(List otherContacts) {
		this.otherContacts = otherContacts;
	}
	
}

 

 

 

 

 

 

同时在数据库中中添加相关的user数据

我的mongodb数据添加两个用户如下:

 

{
  "_id" : ObjectId("558915caa668aa7b08eb1197"),
  "_class" : "com.test.domain.entity.User",
  "username" : "admin",
  "password" : "202cb962ac59075b964b07152d234b70",
  "permissionList" : ["parseResultAdd", "parseResultAddMulti", "usermanage", "loglist", "resultlist"],
  "roleList" : ["admin"]
}
{
  "_id" : ObjectId("55891777a668e496191c6eb1"),
  "_class" : "com.test.domain.entity.User",
  "username" : "test",
  "password" : "202cb962ac59075b964b07152d234b70",
  "permissionList" : ["parseResultAdd", "parseResultAddMulti", "resultlist"],
  "roleList" : ["normal"]
}

 

"password" : "202cb962ac59075b964b07152d234b70"对应密码为123。

 

这里采用了shiro自带的加密方式。详情看下面的代码。

 

添加用户代码为:

 

package com.test.web.support.shiro;

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

import org.apache.shiro.authc.credential.DefaultPasswordService;
import org.apache.shiro.authc.credential.PasswordService;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import com.test.domain.entity.User;
import com.test.domain.repository.UserReposity;

public class UserAdd {

	public static void main(String[] args) {
		  final String[] paths = new String[] {  
	                "src/main/resource/com/test/web/conf/mongodb/spring-mongodb.xml"};
	        final ApplicationContext context = new FileSystemXmlApplicationContext(  
	                paths); // ClassPathXmlApplicationContext  
	        final UserReposity processor = (UserReposity) context  
	                .getBean("userReposity");  
		User user=new User();
		String username="admin";
		String password="123";
		user.setUsername(username);		
	    String encrypted =  new SimpleHash("MD5",password,null,1).toHex();
	    //这里的加密方式要与配置对应
	    //指定hash算法为MD5;  无默认值,必须指定为MD5或者SHA-1等
	    //指定散列次数为1次;默认为1
        // 指定Hash散列值使用Hex加密存储。value="false"表明hash散列值用用Base64-encoded存储。默认为true 
	    user.setPassword(encrypted);
	    
	    List permissionList=new ArrayList();
	    List roleList=new ArrayList();
	    permissionList.add("parseResultAdd");
	    permissionList.add("parseResultAddMulti");
	    permissionList.add("usermanage");
	    permissionList.add("loglist");
	    permissionList.add("resultlist");	   	  
	    roleList.add("admin");
	    user.setPermissionList(permissionList);
	    user.setRoleList(roleList);
	    processor.saveObject(user);
	}
}

   

 

String encrypted =  new SimpleHash("MD5",password,null,1).toHex();

使用shiro注册增加用户时的加密方式要与自己的设置想匹配。

spring-shiro.xml中配置为:

 

 
		
			
				
			
				
	 

验证时为:

 

springMVC与shiro集成_第1张图片

 

 



添加后如图所示:

springMVC与shiro集成_第2张图片

springMVC与shiro集成_第3张图片

 

 

导入jar

因为我们的是maven工程,所以把shiro相关的包写入pom.xml文件。

在pom.xml中添加

 

     
        
      org.apache.shiro    
      shiro-core    
      1.2.2    
        
        
      org.apache.shiro    
      shiro-web    
      1.2.2    
        
        
      org.apache.shiro    
      shiro-spring    
      1.2.2    
       

 

完整版的pom.xml太长,这里就不给出了,可下载源码查看

 

配置web.xml

 

在web.xml里添加shiro 的配置

shiro的filter应该放在struts2的 filter的上面

 

     
      
    shiroFilter    
    org.springframework.web.filter.DelegatingFilterProxy    
      
      
    shiroFilter    
    /*    
    


完整版web.xml

 

 




encodingFilter
com.test.web.servlet.filter.EncodingFilter


shiroFilter
org.springframework.web.filter.DelegatingFilterProxy

targetFilterLifecycle
true



encodingFilter
/*


shiroFilter
/*


springMVC
org.springframework.web.servlet.DispatcherServlet

contextConfigLocation
classpath:spring-web.xml

1


springMVC
/


org.springframework.web.context.ContextLoaderListener


contextConfigLocation

            classpath:spring-web.xml
        






_sid

COOKIE


404
/404


javax.servlet.ServletException
/error



*.jsp
UTF-8
false



 

 

建立dbRelm

 

 

 

主要是扩展AuthorizingRealm, 实现在数据库中查询是否有该帐号密码,实现验证。

我新建一个MyShiro的class

MyShiro.java

 

package com.test.web.support.shiro;




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.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;




import com.test.domain.entity.User;
import com.test.domain.repository.UserReposity;




public class MyShiro extends AuthorizingRealm{  




@Autowired
UserReposity userReposity;
  /** 
     * 权限认证 
     */  
    @Override  
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {  




     
    //获取登录时输入的用户名  
        String loginName=(String) principalCollection.fromRealm(getName()).iterator().next();  
        //到数据库查是否有此对象  
        User user=userReposity.findByName(loginName);  
        if(user!=null){  
            //权限信息对象info,用来存放查出的用户的所有的角色(role)及权限(permission)  
            SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();  
            //用户的角色集合  
            info.addRoles(user.getRoleList());  
            //用户的角色对应的所有权限,如果只使用角色定义访问权限,下面的一行可以不要  
              info.addStringPermissions(user.getPermissionList()); 
            
            return info;  
        }  
        return null;  
    }  
  
    /** 
     * 登录认证; 
     */  
    @Override  
    protected AuthenticationInfo doGetAuthenticationInfo(  
            AuthenticationToken authenticationToken) throws AuthenticationException {  
    
    //UsernamePasswordToken对象用来存放提交的登录信息  
        UsernamePasswordToken token=(UsernamePasswordToken) authenticationToken;  
        //查出是否有此用户  
        User user=userReposity.findByName(token.getUsername());  
        if(user!=null){  
            //若存在,将此用户存放到登录认证info中  
            return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());  
        }  
        return null;  
    }












}

 

 

同时还应配置mongodb的访问xml和userReposity的bean定义,这里不给出了,详情可下载源码

主要有两部分 

一是对数据库具体访问的接口实现 

springMVC与shiro集成_第4张图片

二是 spring-mongodb.xml 

 



  
     
	
		
	  
     		
          
      	 

      
      
 	
       	  
         
       

 

 

 

 

 

 

 

新建用于登录,登出,权限跳转的控制HomeController 

HomeController.java

 

package com.test.web.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.test.domain.entity.User;

public class HomeController {
	   @RequestMapping(value="/login",method=RequestMethod.GET)  
	    public String loginForm(Model model){  
	        model.addAttribute("user", new User());  
	        return "/login";  
	    }  
	      
	    @RequestMapping(value="/login",method=RequestMethod.POST)  
	    public String login(User user,BindingResult bindingResult,RedirectAttributes redirectAttributes){  
	        try {  
	            if(bindingResult.hasErrors()){  
	                return "/login";  
	            }  
	            //使用权限工具进行用户登录,登录成功后跳到shiro配置的successUrl中,与下面的return没什么关系!  
	            SecurityUtils.getSubject().login(new UsernamePasswordToken(user.getUsername(), user.getPassword()));  
	            return "/home";  
	        } catch (AuthenticationException e) {  
	            redirectAttributes.addFlashAttribute("message","用户名或密码错误");  
	            return "redirect:/login";  
	        }  
	    }  
	      
	    @RequestMapping(value="/logout",method=RequestMethod.GET)    
	    public String logout(RedirectAttributes redirectAttributes ){   
	        //使用权限管理工具进行用户的退出,跳出登录,给出提示信息  
	        SecurityUtils.getSubject().logout();    
	        redirectAttributes.addFlashAttribute("message", "您已安全退出");    
	        return "redirect:/login";  
	    }   
	      
	    @RequestMapping("/403")  
	    public String unauthorizedRole(){  
	        return "/403";  
	    }  
}

 

 

 

 

 

新建登录显示页面

三个页面放在views文件夹中 login.jsp,home.jsp,403.jsp

login.jsp

 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>  
  
  
    
    My JSP 'MyJsp.jsp' starting page  
    
    
    
    

登录页面----${message }

用户名:
密   码:
submit

 

页面上的commandName的user需要与HomeController中

   @RequestMapping(value="/login",method=RequestMethod.GET)  
   public String loginForm(Model model){  
       model.addAttribute("user", new User());  
       return "/login";  
   }  

里的user对应。属性名对应。

 

 

home.jsp

 

 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>  
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>  
  
  
    
    用户列表  
    
    
    

${message }

用户列表--添加用户---退出登录

权限列表-----当前登录用户名

用户已经登录显示此内容
admin角色登录显示此内容
normal角色登录显示此内容
**normal or admin 角色用户登录显示此内容**
loglist权限用户显示此内容
不具有loglist权限的用户显示此内容

 

 

403.jsp

 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>  
  
  
    
    权限错误  
    
    
    
    

对不起,您没有权限请求此连接!

 

 

 

 

在Spring中配置

spring-shiro.xml

 





	

	 
		
			
				
			
				
	 
	
	
		
			
				
					
						
						
					
				
			
		
		
				
	

	
	
		
		
		
		
		
			
				
					
				
			
		
		
			
				/login = anon
				  
                
                  
               
                  
               
               
               
                    
                
			
		
	


这里对页面的访问权限可以相应调节。

 

 

 

结果展示

启动后分别用admin和test账户登录可以看到根据角色和权限已经能显示不同的内容

springMVC与shiro集成_第5张图片

springMVC与shiro集成_第6张图片

 

 

Controller中获取用户信息

 

shiro 管理登录,获取登录信息的方式常用的是:

Subject sub = SecurityUtils.getSubject();

Object obj = sub.getPrincipal();

这里的 obj 是字符串,还是某个实体,取决于 ShiroRealm 类的设置,代码如下:

 

也就是看doGetAuthenticationInfo方法中的存放的是实体还是具体某个字段。

  /** 
     * 登录认证; 
     */  
    @Override  
    protected AuthenticationInfo doGetAuthenticationInfo(  
            AuthenticationToken authenticationToken) throws AuthenticationException {  
    
    //UsernamePasswordToken对象用来存放提交的登录信息  
        UsernamePasswordToken token=(UsernamePasswordToken) authenticationToken;  
        //查出是否有此用户  
        User user=userReposity.findByName(token.getUsername());  
        if(user!=null){  
            //若存在,将此用户存放到登录认证info中  
            return new SimpleAuthenticationInfo(user, user.getPassword(), getName());  
        }  
        return null;  
    }

 

如果像上面这样设置,SimpleAuthenticationInfo中存放的是user实体,读取登录信息就是

 

如果设置登录信息的地方如下:

  /** 
     * 登录认证; 
     */  
    @Override  
    protected AuthenticationInfo doGetAuthenticationInfo(  
            AuthenticationToken authenticationToken) throws AuthenticationException {  
    
    //UsernamePasswordToken对象用来存放提交的登录信息  
        UsernamePasswordToken token=(UsernamePasswordToken) authenticationToken;  
        //查出是否有此用户  
        User user=userReposity.findByName(token.getUsername());  
        if(user!=null){  
            //若存在,将此用户存放到登录认证info中  
            return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());  
        }  
        return null;  
    }

 

SimpleAuthenticationInfo中存放的是user实体中username的字段,读取登录信息就是

String userName = (String) SecurityUtils.getSubject().getPrincipal();

 

 

ps:启用ini配置

realm如果不想用数据库,也可以用文本形式配置,如下

spring-shiro.xml中注释mongoRealm,启用iniRealm

 


		
	

	
	
	
		
			
				
					
						
						
					
				
			
		
		  
			
	

 

新建shiro.ini

springMVC与shiro集成_第7张图片

 

 

 

 

shiro.ini 里是帐号密码和角色

 

[users]
admin = 123, admin
test = 123, normal
[roles]
normal= *
admin = *

当然还可以有其它配置

 

springMVC与shiro集成_第8张图片
 

 

 

 

 

源码下载:

springshiro
 

 

 

 

 

你可能感兴趣的:(java,shiro)