Shiro+SpringMVC+Spring集成

近期由于使用shiro作为安全框架作为项目中要使用的权限管理,在此分享一下shiro于spring和springmvc集成的demo

1.首先添加web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0"  metadata-complete="true">
	<display-name>shiro测试</display-name>
	
	<!-- shiroFilter -->
	<filter>
		<filter-name>shiroFilter</filter-name>
		<!-- 代理类,自动到spring配置文件中找shiro配置文件 -->
		<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>
	
	<!-- 加载spring配置文件 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:beans.xml</param-value>
	</context-param>

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- springmvc配置文件加载 -->
	<servlet>
		<servlet-name>springmvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:springmvc.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>springmvc</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
	<!-- 使用spring解决乱码问题 -->
	<filter>  
		<filter-name>encodingFilter</filter-name>  
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  
		<init-param>  
		<param-name>encoding</param-name>  
		<param-value>UTF-8</param-value>  
		</init-param>
		<init-param>  
		    <param-name>forceEncoding</param-name>  
		    <param-value>true</param-value>  
		  </init-param>  
	</filter>
	  
	<filter-mapping>  
	  <filter-name>encodingFilter</filter-name>  
	  <url-pattern>/*</url-pattern>  
	</filter-mapping>  
	
	<welcome-file-list>
        <welcome-file>login.jsp</welcome-file>
    </welcome-file-list>
</web-app>

 2.SpringMVC配置文件springmvc.xml

<?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:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans.xsd 
						http://www.springframework.org/schema/mvc 
						http://www.springframework.org/schema/mvc/spring-mvc.xsd 
						http://www.springframework.org/schema/context 
						http://www.springframework.org/schema/context/spring-context.xsd 
						http://www.springframework.org/schema/aop 
						http://www.springframework.org/schema/aop/spring-aop.xsd 
						http://www.springframework.org/schema/tx 
						http://www.springframework.org/schema/tx/spring-tx.xsd ">
				
		<!-- 	<bean id="myController" name="/control.action" class="com.cai.controller.MyController"></bean>	 -->
		<!-- 支持注解驱动 -->
		<mvc:annotation-driven/>	
		
		<!-- shiro中注解起作用必须配置在springmvc配置文件中,配置在其他地方无效 -->
		<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>
		<!-- 配置异常跳转页面,此处异常页面是使用shiro注解时没有权限访问的跳转页面,不配置则会报500错误 -->
		<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
			<property name="exceptionMappings">
				<props>
					<prop key="org.apache.shiro.authz.UnauthorizedException">
					<!-- 没有权限时跳转的页面 -->
						/unauthorized
					</prop>
					<prop key="org.apache.shiro.authz.UnauthenticatedException">
					<!-- 认证错误时跳转的页面 -->
						/unauthenticated
					</prop>
				</props>
			</property>
		</bean>
		
		<!-- 组件扫描的包 -->	
		<context:component-scan base-package="com.cai.controller"/>
		<!-- 静态资源目录 -->
		<mvc:resources mapping="/js/**" location="/js/" />
		<mvc:resources mapping="/images/**" location="/images/" />
		<mvc:resources mapping="/css/**" location="/css/" />
		<mvc:resources mapping="/common/**" location="/common/" />
		
		
		<!-- 配置视图解析器 -->
		<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		
			<!-- 通过setter方法注入前缀 -->
			<property name="prefix" value="/WEB-INF/pages/"/>
			<!-- 通过setter方法注入后缀 -->				
			<property name="suffix" value=".jsp"></property>
		</bean>
</beans>

3.Spring配置文件beans.xml

<?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:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
			http://www.springframework.org/schema/beans/spring-beans.xsd 
			http://www.springframework.org/schema/mvc 
			http://www.springframework.org/schema/mvc/spring-mvc.xsd 
			http://www.springframework.org/schema/context 
			http://www.springframework.org/schema/context/spring-context.xsd 
			http://www.springframework.org/schema/aop 
			http://www.springframework.org/schema/aop/spring-aop.xsd 
			http://www.springframework.org/schema/tx 
			http://www.springframework.org/schema/tx/spring-tx.xsd ">
			 
    <!-- 组件扫描 -->
    <context:component-scan base-package="com.cai.*"/>
        
    <!--数据库配置:配置jdbc.properties  -->
    <context:property-placeholder location="classpath:jdbc.properties"/>
	
	<!-- 3、配置dataSource数据源c3p0 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${jdbc.driverClassName}"/>
		<property name="jdbcUrl" value="${jdbc.url}"/>
		<property name="user" value="${jdbc.username}"/>
		<property name="password" value="${jdbc.password}"/>
		
		<!-- <property name="maxPoolSize" value="${c3p0.pool.maxPoolSize}"/>
		<property name="minPoolSize" value="${c3p0.pool.minPoolSize}"/>
		<property name="initialPoolSize" value="${c3p0.pool.initialPoolSize}"/>
		<property name="acquireIncrement" value="${c3p0.pool.acquireIncrement}"/> -->
	</bean>
	
	<!-- 数据源使用Spring自带的jdbctemplate -->
	 <bean id="jdbcTemplate" name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<bean id="userDao" name="userDao" class="com.cai.dao.UserDao">
		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
	</bean>
	
	<bean id="baseDao" name="baseDao" class="com.cai.dao.BaseDao">
		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
	</bean>
	
	<!-- <bean id="baseDao" name="baseDao" class="com.cai.dao.BaseDao">
		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
	</bean> -->
	
	<!-- 事务管理 -->
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 导入shiro配置文件 -->
	<import resource="shiro.xml"/>
	
    	
</beans>

 4.jdbc.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/shiro?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456

 5.缓存ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="ehcache.xsd"
         updateCheck="true" monitoring="autodetect"
         dynamicConfig="true">

  <defaultCache maxElementsInMemory="10000"
                    eternal="false"
                    timeToIdleSeconds="120" 
                    timeToLiveSeconds="120" 
                    overflowToDisk="true"
                    maxElementsOnDisk="10000000" 
                    diskPersistent="false"
                    diskExpiryThreadIntervalSeconds="120" 
                    memoryStoreEvictionPolicy="LRU" />
    
</ehcache>

 6.java代码

MD5加密

public class MD5Utils {
	/**
	 * 使用md5的算法进行加密
         *  此处使用的是shiro自带的md5加密方法
	 */
	public static String md5(String password) {
		Md5Hash md5 = new Md5Hash(password);
		return md5.toString();
	}
	

}

 实体类javabean

public class User {
    private int id;
    private String username;//用户名
    private String password;//用户密码
    private String realname;//真实名字
    private String email;//emai地址
    private String phone;//电话号码
    
    private List<Role> roles = new ArrayList<Role>();
    /**
     * @return the roles
     */
    public List<Role> getRoles() {
        return roles;
    }
    /**
     * @param roles the roles to set
     */
    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }
        ....都是get、set方法
    
    
}

 

public class Role {
    private int id;
    private String rolename;//角色名
    private String roletype;//角色类型
    
    List<Permission> perms = new ArrayList<Permission>();
    /**
     * @return the perms
     */
    public List<Permission> getPerms() {
        return perms;
    }
    /**
     * @param perms the perms to set
     */
    public void setPerms(List<Permission> perms) {
        this.perms = perms;
    }
        //...get set方法
}

 

public class Permission {
    private int id;
    private String permname;//权限名称
    private String operation;//权限操作
    private String description;//权限描述
    /**
     * @return the id
     */
    public int getId() {
        return id;
    }
    /**
     * @param id the id to set
     */
    public void setId(int id) {
        this.id = id;
    }
//...get set方法
}

 Dao层

@Repository
public class BaseDao extends JdbcDaoSupport {
    
    /**
     * 条件查询
     * @param sql
     * @param id
     * @return
     */
    public Map<String, Object> querySingle(String sql,Object... args) {
        return this.getJdbcTemplate().queryForMap(sql, args);
    }
    
    /**
     * 根据sql查询
     * @param sql
     * @return
     */
    public Map<String, Object> queryAll(String sql) {
        return this.getJdbcTemplate().queryForMap(sql);
    }
    
    /**
     * 查询集合
     * @param sql
     * @return
     */
    public List<Map<String, Object>> queryList(String sql) {
        return this.getJdbcTemplate().queryForList(sql);
    }
    
    /**
     * 条件查询集合
     * @param sql
     * @param args
     * @return
     */
    public List<Map<String, Object>> queryList(String sql, Object... args) {
        return this.getJdbcTemplate().queryForList(sql, args);
    }
    
    /**
     * 更新记录条数
     * @param sql
     * @return
     */
    public int update(String sql) {
        return this.getJdbcTemplate().update(sql);
    }
    
    /**
     * 按条件更新
     * @param sql
     * @param args
     * @return
     */
    public int update(String sql, Object... args) {
        return this.getJdbcTemplate().update(sql, args);
    }
    
    /**
     * 添加记录
     * @param sql
     */
    public void add(String sql) {
        this.getJdbcTemplate().execute(sql);
    }
    
    /**
     * 删除记录
     * @param sql
     */
    public void delete(String sql) {
        this.getJdbcTemplate().execute(sql);
    }
}

 

@Repository
public class UserDao extends JdbcDaoSupport {
    
    /**
     * 登录查询
     * @param sql
     * @param username
     * @param password
     * @return
     */
    public Map<String, Object> loginQuery(String sql, String username, String password) {
        return this.getJdbcTemplate().queryForMap(sql, username, password);
    } 
    /**
     * 登录查询
     * @param sql
     * @param username
     * @param password
     * @return
     */
    public Map<String, Object> loginQuery(String sql, String username) {
        return this.getJdbcTemplate().queryForMap(sql, username);
    } 

}

 Service 层

@Service
public class UserService {

    @Autowired
    UserDao userDao;
    
    @Autowired
    BaseDao baseDao;
    
    public Map<String, Object> queryLogin(String username, String password) {
        String sql = "select username, password from user where username=? and password=?";
        return userDao.loginQuery(sql, username, password);
    }
    
    public User queryLogin(String username) {
        String sql = "select * from user where username=?";
        Map<String, Object> query = userDao.loginQuery(sql,username);
        User user = new User();
        if(query != null && query.size() > 0) {
            if(query.get("id") != null) {
                user.setId(Integer.parseInt(query.get("id").toString()));
            }
            if(query.get("username") != null) {
                user.setUsername(query.get("username").toString());
            }
            if(query.get("password") != null) {
                user.setPassword(query.get("password").toString());
            }
            if(query.get("realname") != null) {
                user.setRealname(query.get("realname").toString());
            }
            if(query.get("email") != null) {
                user.setEmail(query.get("email").toString());
            }
            if(query.get("phone") != null) {
                user.setPhone(query.get("phone").toString());
            }
            
        }
        return user;
    }
}

 

@Service
public class ShiroService {
    @Autowired
    BaseDao baseDao;
    
    /**
     * 根据角色id获取对应的权限id
     * @param roleid
     * @return
     */
    public List<Map<String, Object>> getPermissions(int roleid) {
        String sql = "select * from role_permission where role_id=?";
        return baseDao.queryList(sql, roleid);
    }
    
    /**
     * 通过用户id获取角色
     * @param userid
     * @return
     */
    public List<Map<String, Object>> getRoles(int userid){
        String sql = "select * from role where id in (select role_id from user_role where user_id=?)";
        return baseDao.queryList(sql, userid);
    }
    
    /**
     * 添加权限id
     * @param permid
     */
    /*public void addPerm(int permid) {
        String sql = "insert into role_permission";
    }*/
    
    /**
     * 查询所有的权限
     * @param role
     * @return
     */
    public List<Map<String, Object>> getPermissions(Role role) {
        String sql = "select * from permission where id in (SELECT permission_id from role_permission WHERE role_id=?)";
        return baseDao.queryList(sql, role.getId());
    } 
    
    /**
     * 查询所有的角色
     * @param user
     * @return
     */
    public List<Map<String, Object>> getRoles(User user) {
        String sql = "select * from role where id in (select role_id from user_role where user_id=?)";
        return baseDao.queryList(sql, user.getId());
    }
}

 Shiro核心

@Service
public class MyRealm extends AuthorizingRealm{
    @Autowired
    ShiroService shiroService;
    @Autowired
    UserService userService;
    /* (non-Javadoc)
     * @see org.apache.shiro.realm.AuthorizingRealm#doGetAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection)
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        //获取当前登录用户名
        //String account = (String) principals.fromRealm(getName()).iterator().next();
//        String account = (String)getAvailablePrincipal(principals);
        Subject subject = SecurityUtils.getSubject();
        String account = (String) subject.getPrincipal();
        User user = userService.queryLogin(account);
        List<Map<String,Object>> roleList = shiroService.getRoles(user);
        for (Map<String, Object> roles : roleList) {
            authorizationInfo.addRole(roles.get("roletype").toString());
            Role role = new Role();
            role.setId(Integer.parseInt((roles.get("id").toString())));
            List<Map<String, Object>> permissionsList = shiroService.getPermissions(role);
            for (Map<String, Object> perms : permissionsList) {
                authorizationInfo.addStringPermission(perms.get("operation").toString());
            }
        }
        return authorizationInfo;
    }

    /* (non-Javadoc)
     * @see org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken)
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {
        //根据用户名查询数据库
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken)token;//封装认证对象
        User user = userService.queryLogin(usernamePasswordToken.getUsername());
        if(user == null) {
            //用户不存在
            return null;
        }
        //返回密码
        AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());//getName获取当前的realm
        //比较密码
        return authenticationInfo;
    }

}

Controller

@Controller
public class UserController {
    @Autowired
    UserService userService;
    
    @RequestMapping(value="/login") 
    public String login (HttpServletRequest request) {
        //非shiro登录
        /*String username = request.getParameter("username");
        String password = request.getParameter("password");
        Map<String, Object> queryLogin = userService.queryLogin(username, MD5Utils.md5(password));
        if(queryLogin != null) {
            return "success";
        } else {
            return "fail";
        }*/
        return "login";
    }
    
    @RequestMapping(value="/checklogin")
    @ResponseBody
    public String checkLogin(HttpServletRequest request) {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, MD5Utils.md5(password));
        token.setRememberMe(true);
        try {
            subject.login(token);
            request.getSession().setAttribute("account", username);
        } catch (AuthenticationException e) {
            //e.printStackTrace();
            return "/login";
            
        }
        
        return "/first";
    }
    
    @RequestMapping(value="/manage/first")
    public String main(HttpServletRequest request) {
        //String 
        return "/manage/first";
    }
    
    @RequestMapping(value="/operation/add")
    public String add(HttpServletRequest request) {
        return "/operation/add";
    }
    
    //@RequiresRoles("administrator")
    @RequestMapping(value="/operation/delete")
    public String delete(HttpServletRequest request) {
        Subject subject = SecurityUtils.getSubject();
        if(subject.hasRole("administrator")) {
            return "/operation/delete";
        } else {
            return "/manage/unauthorized";
        }
    }
    
    
    @RequestMapping(value="/operation/update")
    @RequiresRoles("header")
    public String update(HttpServletRequest request) {
        return "/operation/update";
    }
    
    @RequestMapping(value="/operation/query")
    public String query(HttpServletRequest request) {
        return "/operation/query";
    }
    
    @RequestMapping(value="/search/search")
    public String search(HttpServletRequest request) {
        return "/search/search";
    }
    @RequestMapping(value="/manage/unauthorized")
    public String error(HttpServletRequest request) {
        return "/manage/unauthorized";
    }
    
    @RequestMapping(value="/logout", method=RequestMethod.GET) 
    public String logout() {
        Subject subject = SecurityUtils.getSubject();
        if(subject.isAuthenticated()) {
            subject.logout();
            //return "login";
        }
        return "redirect:login";
    }

}

 jsp页面在下面的文件中,下载后创建数据库执行sql,直接导入项目就行 了

 

 

猜你喜欢

转载自shareisattitude.iteye.com/blog/2199553
今日推荐