SpringMVC+maven
项目需要使用shiro,所以自学了几天,仅提供给新手,请根据文档查看…该项目仅是测试项目,并不完善,只实现了需要使用的基本功能,并且只提供了使用shiro模块的代码。楼主新人第一次写,如有问题希望能提出来,由衷的感谢。
首先是pom.xml:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.0</version>
</dependency>
以下是web.xml配置:
<filter>
<!-- filter-name需要和shiro的过滤器id一致 -->
<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>
以下是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:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- shior配置 begin -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- <property name="cacheManager" ref="cacheManager" /> -->
<!-- 自定义的Realm -->
<property name="realm" ref="myRealm" />
</bean>
<!-- 缓存 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
</bean>
<bean id="myRealm"
class="com.renai.shop.service.admin.AuthenticationRealm">
<!-- 加密 -->
<!-- <property name="credentialsMatcher"> <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="SHA-256"/> <property name="storedCredentialsHexEncoded"
value="false"/> </bean> </property> -->
</bean>
<!-- SecurityManager是shiro的核心,协调shiro的各个组件 -->
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
<!-- shiro过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login/gotoLogin.html" />
<property name="unauthorizedUrl" value="/unauthorized.jsp" />
<property name="filterChainDefinitions">
<value>
/login/gotoLogin.html = anon
/login/login.html = anon
/login/** = authc
/sys/** = authc
<!-- /sys/add/** = authc, roles[manager]
/sys/update/** = authc, roles[admin]
/sys/delete/** = authc, perms[delete] -->
</value>
</property>
</bean>
</beans>
以下是自定义的Realm类:
package com.renai.shop.service.admin;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
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.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import com.renai.shop.dao.mapper.SysDictionaryMapper;
import com.renai.shop.model.admin.AdmPermission;
import com.renai.shop.model.admin.AdmRole;
import com.renai.shop.model.admin.AdmUserInfo;
/**
* @作者 zjm
* @类说明:
* @创建日期 2015年03月19日
* @版本 V 1.0
*/
public class AuthenticationRealm extends AuthorizingRealm {
@Autowired
private SysDictionaryMapper sysDictionaryMapper;
/**
* 给权限
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) throws AuthenticationException{
System.out.println("--------------------------doGetAuthorizationInfo--------------------------");
//获取用户名
String userName = (String) getAvailablePrincipal(principals);
SimpleAuthorizationInfo info = null;
if (StringUtils.isNotBlank(userName)) {
//按照用户名查询
AdmUserInfo userInfo = sysDictionaryMapper.getUserInfoByUserName(userName);
if (userInfo != null) {
//获取用户的角色,并保存,过滤角色时使用
List<AdmRole> roles = userInfo.getRoles();
Set<String> roleNames = new HashSet<String>();
Set<String> permissions = new HashSet<String>();
for (AdmRole role : roles) {
roleNames.add(role.getName());
//获取角色的权限,并保存,过滤权限时使用
for (AdmPermission permission : role.getPermissions()) {
permissions.add(permission.getOperation());
}
}
//保存角色和权限
info = new SimpleAuthorizationInfo(roleNames);
info.setStringPermissions(permissions);
}
} else {
System.out.println("--------------------------用户名不能为空!--------------------------");
}
return info;
}
/**
* 登陆验证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
System.out.println("--------------------------doGetAuthenticationInfo--------------------------");
//获取登录用户的信息
UsernamePasswordToken upToken = (UsernamePasswordToken)token;
SimpleAuthenticationInfo info = null;
String userName = upToken.getUsername();
String passWord = String.valueOf(upToken.getPassword());
AdmUserInfo userInfo = sysDictionaryMapper.login(userName, passWord);
if (userInfo == null) {
//抛出的异常在LoginController中处理
throw new UnknownAccountException("用户名或密码错误");
}
try {
info = new SimpleAuthenticationInfo(userName, passWord, getName());
} catch (Exception e) {
throw new AuthenticationException("验证失败", e);
}
return info;
}
}
登录Controller:
package com.renai.shop.admin.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.renai.shop.filter.admin.AdmMenuFilter;
import com.renai.shop.model.admin.AdmMenu;
import com.renai.shop.model.admin.AdmUserInfo;
import com.renai.shop.service.admin.api.ISysDictionaryService;
/**
* @作者 zjm
* @类说明:
* @创建日期 2015年03月19日
* @版本 V 1.0
*/
@RequestMapping(value = "/login")
@Controller
public class LoginController {
@Autowired
private ISysDictionaryService sysDictionaryService;
@RequestMapping(value = "/gotoLogin.html")
public String goToLogin(HttpServletRequest request,
HttpServletResponse response, ModelMap modelMap) {
return "login";
}
@RequestMapping(value = "/login.html")
@ResponseBody
public String login(HttpServletRequest request,
HttpServletResponse response, ModelMap modelMap,
@Param(value = "username") String username,
@Param(value = "password") String password) {
UsernamePasswordToken token = new UsernamePasswordToken(username,
password);
Subject subject = SecurityUtils.getSubject();
try {
//调用AuthenticationRealm的doGetAuthenticationInfo
subject.login(token);
} catch (UnknownAccountException ex) {
System.out.println("用户名没有找到" + ex.toString());
return "error";
} catch (IncorrectCredentialsException ex) {
System.out.println("用户名密码不匹配" + ex.toString());
return "error";
} catch (AuthenticationException e) {
System.out.println("其他的登录错误" + e.toString());
return "error";
} catch (Exception e) {
System.out.println("登陆失败" + e.toString());
return "error";
}
// 记住令牌
token.setRememberMe(true);
return "success";
}
@RequestMapping(value = "/goToIndex.html")
public String goToIndex(HttpServletRequest request,
HttpServletResponse response, ModelMap modelMap) {
Subject subject = SecurityUtils.getSubject();
String userName = subject.getPrincipal().toString();
if (StringUtils.isNotBlank(userName)) {
AdmUserInfo userInfo = sysDictionaryService.getUserInfoByUserName(userName);
if (userInfo != null ) {
AdmMenuFilter filter = new AdmMenuFilter();
filter.setMenuType(1);
if (userInfo.getRoles().size() > 0) {
//按照角色获取用户的菜单
List<AdmMenu> menuList = sysDictionaryService
.selectMenuByRolesId(userInfo.getAdmUserRoleInfos(), filter);
request.getSession().setAttribute("menuList", menuList);
}
}
}
return "index";
}
@RequestMapping(value = "/goToDefault.html")
public String goToDefault(HttpServletRequest request,
HttpServletResponse response, ModelMap modelMap) {
return "default";
}
@RequestMapping(value = "/logout.html")
public String logout(HttpServletRequest request,
HttpServletResponse response, ModelMap modelMap) {
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "login";
}
}
系统Controller:
package com.renai.shop.admin.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import com.renai.shop.filter.admin.AdmMenuFilter;
import com.renai.shop.model.admin.AdmMenu;
import com.renai.shop.model.admin.AdmUserInfo;
import com.renai.shop.service.admin.api.ISysDictionaryService;
/**
* @作者 zjm
* @类说明:
* @创建日期 2015年03月19日
* @版本 V 1.0
*/
@RequestMapping(value = "/sys")
@Controller
public class SysController {
@Autowired
private ISysDictionaryService sysDictionaryService;
@RequestMapping(value = "/getMenuByParent.html")
public String getMenuByParent(HttpServletRequest request,
HttpServletResponse response, ModelMap modelMap,
@Param(value = "parentId") int parentId) {
Subject subject = SecurityUtils.getSubject();
String userName = subject.getPrincipal().toString();
if (StringUtils.isNotBlank(userName)) {
AdmUserInfo userInfo = sysDictionaryService.getUserInfoByUserName(userName);
if (userInfo != null) {
AdmMenuFilter filter = new AdmMenuFilter();
filter.setMenuType(2);
filter.setParentId(parentId);
// 查询权限
if (userInfo.getRoles().size() > 0) {
List<AdmMenu> thirdMenuList = sysDictionaryService
.selectMenuByRolesId(userInfo.getAdmUserRoleInfos(), filter);
request.getSession().setAttribute("thirdMenuList", thirdMenuList);
}
}
}
return "ajax/ajaxGetMenu";
}
}
以下是页面:
使用shiro的标签需要引用:
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
以下是按照登录时保存的权限显示按钮
<div class="tools">
<ul class="toolbar">
<shiro:hasPermission name="add">
<li class="click" onclick="add()"><span><img
src="${ctx}/skin/images/t01.png"></span>添加</li>
</shiro:hasPermission>
<shiro:hasPermission name="update">
<li class="click" onclick="update()"><span><img
src="${ctx}/skin/images/t02.png"></span>修改</li>
</shiro:hasPermission>
<shiro:hasPermission name="delete">
<li onclick="deletes()"><span><img
src="${ctx}/skin/images/t03.png"></span>删除</li>
</shiro:hasPermission>
</ul>
</div>
以下是项目数据
表
菜单表
角色表
权限表
以下是项目页面部分截图
第一个是“boos”角色登陆
第二个是“manager”角色登陆
第三个是“admin”角色登陆