====== spring整合shiro实现权限管理 ====== ===== 加入pom依赖 ===== org.apache.shiro shiro-core 1.2.3 org.apache.shiro shiro-web 1.2.3 org.apache.shiro shiro-spring 1.2.3 ===== web.xml ===== Archetype Created Web Application contextConfigLocation classpath*:/application-*.xml, classpath*:/hessian-servlet.xml encodingFilter org.springframework.web.filter.CharacterEncodingFilter encoding UTF-8 forceEncoding true encodingFilter /* shiroFilter org.springframework.web.filter.DelegatingFilterProxy targetFilterLifecycle true shiroFilter *.htm org.springframework.web.context.ContextLoaderListener org.springframework.web.util.IntrospectorCleanupListener dispatcher org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath*:/spring-mvc.xml 1 dispatcher *.htm hessian org.springframework.web.servlet.DispatcherServlet 4 hessian /hessian/* index.jsp JSPConfiguration *.jsp UTF-8 ===== application-shiro.xml ===== /login.htm=anon /logout.htm=logout /unauthorized.htm=anon /** = authc,perms ===== UrlPermissionsFilter.java ===== package com.gxx.manage.shiro; import java.io.IOException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter; /** *
*
Title:
*
* 基于URL的权限判断过滤器 我们自动根据URL产生所谓的权限字符串,这一项在Shiro示例中是写在配置文件里面的,默认认为权限不可动态配置 * URL举例:/User/create.do?***=*** -->权限字符串:/User/create.do
*
Description:
*
*

* none

*
* * @author Administrator * @version 1.0, 2015年9月20日 * @since manage * */ public class UrlPermissionsFilter extends PermissionsAuthorizationFilter { /** * 日志处理器 */ Logger logger = Logger.getLogger(UrlPermissionsFilter.class); /** * 指的是在声明url时指定的权限字符串,如/User/create.do=perms[User:create]. * 我们要动态产生这个权限字符串,所以这个配置对我们没用 */ public boolean isAccessAllowed (ServletRequest request, ServletResponse response, Object mappedValue) throws IOException { return super.isAccessAllowed(request, response, buildPermissions(request)); } /** * 根据请求URL产生权限字符串,这里只产生,而比对的事交给Realm * @param request * @return */ protected String[] buildPermissions(ServletRequest request) { String path = ((HttpServletRequest) request).getServletPath(); logger.info("请求地址对应的Url权限:" + path); return new String[]{path}; } }
===== ManageAuthorizingRealm.java ===== package com.gxx.manage.shiro; import java.util.List; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.log4j.Logger; 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.gxx.manage.base.vo.Permission; import com.gxx.manage.base.vo.Role; import com.gxx.manage.base.vo.User; import com.gxx.manage.service.UserService; /** *
*
Title:
*
* 自定义授权领域类 *
*
Description:
*
*

none *

*
* * @author Administrator * @version 1.0, 2015年9月19日 * @since manage * */ public class ManageAuthorizingRealm extends AuthorizingRealm { /** * 日志处理器 */ Logger logger = Logger.getLogger(ManageAuthorizingRealm.class); @Autowired UserService userService; /** * 为当前登录的Subject授予角色和权限 * @see 经测试:本例中该方法的调用时机为需授权资源被访问时 * @see 经测试:并且每次访问需授权资源时都会执行该方法中的逻辑,这表明本例中默认并未启用AuthorizationCache * @see 个人感觉若使用了Spring3.1开始提供的ConcurrentMapCache支持,则可灵活决定是否启用AuthorizationCache * @see 比如说这里从数据库获取权限信息时,先去访问Spring3.1提供的缓存,而不使用Shior提供的AuthorizationCache */ @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { /** * 获取当前登录的用户名,等价于(String)principals.fromRealm(this.getName()).iterator().next() */ String currentUsername = (String)super.getAvailablePrincipal(principals); logger.info("为当前登录的Subject授予角色和权限,用户名:" + currentUsername); User user = userService.getUserByName(currentUsername); if(null == user){ /** * 不存在用户则返回null */ logger.error("不存在用户"); return null; } /** * 为当前用户查询角色和权限 */ SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo(); List roles = userService.queryRolesByUserId(user.getId()); for(Role role : roles){ logger.info("拥有角色:" + role.getRole()); simpleAuthorInfo.addRole(role.getRole()); List permissions = userService.queryPermissionsByRoleId(role.getId()); for(Permission permission : permissions){ logger.info("拥有权限:" + permission.getPermission()); simpleAuthorInfo.addStringPermission(permission.getPermission()); } } return simpleAuthorInfo; } /** * 验证当前登录的Subject */ @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { /** * 获取基于用户名和密码的令牌 * 实际上这个token是从LoginController里面currentUser.login(token)传过来的 * 两个token的引用都是一样的 */ logger.info("验证当前Subject时获取到token为" + ReflectionToStringBuilder. toString(((UsernamePasswordToken)token), ToStringStyle.MULTI_LINE_STYLE)); User user = userService.getUserByName(((UsernamePasswordToken)token).getUsername()); if(null == user){ /** * 不存在用户则返回null */ return null; } /** * 这里不用比较,直接返回就好,shiro会自动比较 */ AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo (user.getName(), user.getPassword(), this.getName()); return authenticationInfo; } }
===== LoginController.java ===== package com.gxx.manage.web.account; import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.LockedAccountException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; /** * UserController * * @author gxx */ @Controller public class LoginController { /** * 日志处理器 */ private final Logger logger = Logger.getLogger(LoginController.class); /** * 访问登录页 * @return */ @RequestMapping(value = "/login", method = RequestMethod.GET) public String loginGet() { logger.info("访问/login"); /** * 如果已登录,直接跳到登录后页面 */ Subject currentUser = SecurityUtils.getSubject(); if( currentUser!=null && currentUser.getPrincipal()!=null ){ return "/index"; } return "account/login"; } /** * 访问无权限页 * @return */ @RequestMapping(value = "/unauthorized") public String unauthorized() { logger.info("访问/unauthorized"); return "unauthorized"; } /** * 登录提交 * @param request * @return */ @RequestMapping(value = "/login", method = RequestMethod.POST) public String loginPost(HttpServletRequest request) { logger.info("登录提交,用户名:[" + request.getParameter("username") + "],密码:[" + request.getParameter("password") + "]"); /** * 自定义授权领域 验证用户 */ Subject currentUser = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(request.getParameter("username"), request.getParameter("password")); try{ currentUser.login(token); } catch (UnknownAccountException uae){ logger.error("未知账户!"); } catch (IncorrectCredentialsException ice){ logger.error("密码错误!"); } catch (LockedAccountException lae){ logger.error("账户锁定!"); }//以及其他异常 /** * 判断是否校验通过 */ if(currentUser.isAuthenticated()){ logger.info("用户验证通过!"); return "/index"; } else { token.clear(); return "account/login"; } } /** * 登出,可以不写,因为配置文件中已配置:/logout.htm=logout * @return @RequestMapping(value = "/logout") public String logout() { logger.info("访问/logout"); /** * shiro登出 Subject subject = SecurityUtils.getSubject(); subject.logout(); return "account/login"; } */ } ===== UserService.java ===== package com.gxx.manage.service; import java.util.List; import com.gxx.manage.base.vo.Permission; import com.gxx.manage.base.vo.Role; import com.gxx.manage.base.vo.User; /** *
*
Title:
*
* 用户服务接口 *
*
Description:
*
*

none *

*
* * @author Administrator * @version 1.0, 2015年6月18日 * @since manage * */ public interface UserService { /** * 新增用户 * @param user */ public void doSaveUser(User user); /** * 根据姓名查用户 * @param name * @return */ public User getUserByName(String name); /** * 根据用户ID查询角色集合 * @param userId * @return */ public List queryRolesByUserId(int userId); /** * 根据角色ID查询权限集合 * @param roleId * @return */ public List queryPermissionsByRoleId(int roleId); }
===== UserServiceImpl.java ===== package com.gxx.manage.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.gxx.manage.base.dao.UserMapper; import com.gxx.manage.base.vo.Permission; import com.gxx.manage.base.vo.Role; import com.gxx.manage.base.vo.User; import com.gxx.manage.service.UserService; /** *
*
Title:
*
* 用户服务实现类 *
*
Description:
*
*

none *

*
* * @author Administrator * @version 1.0, 2015年6月18日 * @since manage * */ @Service("userService") public class UserServiceImpl implements UserService { @Autowired private UserMapper userDao; /** * 新增用户 * @param user */ public void doSaveUser(User user) { userDao.insert(user); } /** * 根据姓名查用户 * @param name * @return */ public User getUserByName(String name) { return userDao.getUserByName(name); } /** * 根据用户ID查询角色集合 * @param userId * @return */ public List queryRolesByUserId(int userId){ return userDao.queryRolesByUserId(userId); } /** * 根据角色ID查询权限集合 * @param roleId * @return */ public List queryPermissionsByRoleId(int roleId){ return userDao.queryPermissionsByRoleId(roleId); } }
===== User.java ===== package com.gxx.manage.base.vo; public class User { private Integer id; private String name; private String password; private String createDate; private String createTime; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name == null ? null : name.trim(); } public String getPassword() { return password; } public void setPassword(String password) { this.password = password == null ? null : password.trim(); } public String getCreateDate() { return createDate; } public void setCreateDate(String createDate) { this.createDate = createDate == null ? null : createDate.trim(); } public String getCreateTime() { return createTime; } public void setCreateTime(String createTime) { this.createTime = createTime == null ? null : createTime.trim(); } } ===== Role.java ===== package com.gxx.manage.base.vo; public class Role { private Integer id; private String role; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getRole() { return role; } public void setRole(String role) { this.role = role == null ? null : role.trim(); } } ===== UserRole.java ===== package com.gxx.manage.base.vo; public class UserRole { private Integer id; private Integer userId; private Integer roleId; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public Integer getRoleId() { return roleId; } public void setRoleId(Integer roleId) { this.roleId = roleId; } } ===== Permission.java ===== package com.gxx.manage.base.vo; public class Permission { private Integer id; private String permission; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getPermission() { return permission; } public void setPermission(String permission) { this.permission = permission == null ? null : permission.trim(); } } ===== RolePermission.java ===== package com.gxx.manage.base.vo; public class RolePermission { private Integer id; private Integer roleId; private Integer permissionId; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getRoleId() { return roleId; } public void setRoleId(Integer roleId) { this.roleId = roleId; } public Integer getPermissionId() { return permissionId; } public void setPermissionId(Integer permissionId) { this.permissionId = permissionId; } } ===== UserMapper.java ===== package com.gxx.manage.base.dao; import java.util.List; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import org.springframework.stereotype.Repository; import com.gxx.manage.base.vo.Permission; import com.gxx.manage.base.vo.Role; import com.gxx.manage.base.vo.User; @Repository public interface UserMapper { int deleteByPrimaryKey(Integer id); int insert(User record); int insertSelective(User record); User selectByPrimaryKey(Integer id); int updateByPrimaryKeySelective(User record); int updateByPrimaryKey(User record); /** * 根据姓名查用户 * @param name * @return */ User getUserByName(String name); /** * 根据用户ID查询角色集合 * @param userId * @return */ @Select("SELECT * FROM ROLE WHERE ID IN(SELECT ROLE_ID FROM USER_ROLE WHERE USER_ID=#{userId})") List queryRolesByUserId(@Param("userId")int userId); /** * 根据角色ID查询权限集合 * @param roleId * @return */ @Select("SELECT * FROM PERMISSION WHERE ID IN(SELECT PERMISSION_ID FROM ROLE_PERMISSION WHERE ROLE_ID=#{roleId})") List queryPermissionsByRoleId(@Param("roleId")int roleId); } ===== RoleMapper.java ===== package com.gxx.manage.base.dao; import org.springframework.stereotype.Repository; import com.gxx.manage.base.vo.Role; @Repository public interface RoleMapper { int deleteByPrimaryKey(Integer id); int insert(Role record); int insertSelective(Role record); Role selectByPrimaryKey(Integer id); int updateByPrimaryKeySelective(Role record); int updateByPrimaryKey(Role record); } ===== UserRoleMapper.java ===== package com.gxx.manage.base.dao; import org.springframework.stereotype.Repository; import com.gxx.manage.base.vo.UserRole; @Repository public interface UserRoleMapper { int deleteByPrimaryKey(Integer id); int insert(UserRole record); int insertSelective(UserRole record); UserRole selectByPrimaryKey(Integer id); int updateByPrimaryKeySelective(UserRole record); int updateByPrimaryKey(UserRole record); } ===== PermissionMapper.java ===== package com.gxx.manage.base.dao; import org.springframework.stereotype.Repository; import com.gxx.manage.base.vo.Permission; @Repository public interface PermissionMapper { int deleteByPrimaryKey(Integer id); int insert(Permission record); int insertSelective(Permission record); Permission selectByPrimaryKey(Integer id); int updateByPrimaryKeySelective(Permission record); int updateByPrimaryKey(Permission record); } ===== RolePermissionMapper.java ===== package com.gxx.manage.base.dao; import org.springframework.stereotype.Repository; import com.gxx.manage.base.vo.RolePermission; @Repository public interface RolePermissionMapper { int deleteByPrimaryKey(Integer id); int insert(RolePermission record); int insertSelective(RolePermission record); RolePermission selectByPrimaryKey(Integer id); int updateByPrimaryKeySelective(RolePermission record); int updateByPrimaryKey(RolePermission record); } ===== UserMapper.xml ===== ID, NAME, PASSWORD, CREATE_DATE, CREATE_TIME delete from user where ID = #{id,jdbcType=INTEGER} insert into user (ID, NAME, PASSWORD, CREATE_DATE, CREATE_TIME) values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{createDate,jdbcType=VARCHAR}, #{createTime,jdbcType=VARCHAR}) insert into user ID, NAME, PASSWORD, CREATE_DATE, CREATE_TIME, #{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{createDate,jdbcType=VARCHAR}, #{createTime,jdbcType=VARCHAR}, update user NAME = #{name,jdbcType=VARCHAR}, PASSWORD = #{password,jdbcType=VARCHAR}, CREATE_DATE = #{createDate,jdbcType=VARCHAR}, CREATE_TIME = #{createTime,jdbcType=VARCHAR}, where ID = #{id,jdbcType=INTEGER} update user set NAME = #{name,jdbcType=VARCHAR}, PASSWORD = #{password,jdbcType=VARCHAR}, CREATE_DATE = #{createDate,jdbcType=VARCHAR}, CREATE_TIME = #{createTime,jdbcType=VARCHAR} where ID = #{id,jdbcType=INTEGER} ===== RoleMapper.xml ===== ID, ROLE delete from role where ID = #{id,jdbcType=INTEGER} insert into role (ID, ROLE) values (#{id,jdbcType=INTEGER}, #{role,jdbcType=VARCHAR}) insert into role ID, ROLE, #{id,jdbcType=INTEGER}, #{role,jdbcType=VARCHAR}, update role ROLE = #{role,jdbcType=VARCHAR}, where ID = #{id,jdbcType=INTEGER} update role set ROLE = #{role,jdbcType=VARCHAR} where ID = #{id,jdbcType=INTEGER} ===== UserRoleMapper.xml ===== ID, USER_ID, ROLE_ID delete from user_role where ID = #{id,jdbcType=INTEGER} insert into user_role (ID, USER_ID, ROLE_ID ) values (#{id,jdbcType=INTEGER}, #{userId,jdbcType=INTEGER}, #{roleId,jdbcType=INTEGER} ) insert into user_role ID, USER_ID, ROLE_ID, #{id,jdbcType=INTEGER}, #{userId,jdbcType=INTEGER}, #{roleId,jdbcType=INTEGER}, update user_role USER_ID = #{userId,jdbcType=INTEGER}, ROLE_ID = #{roleId,jdbcType=INTEGER}, where ID = #{id,jdbcType=INTEGER} update user_role set USER_ID = #{userId,jdbcType=INTEGER}, ROLE_ID = #{roleId,jdbcType=INTEGER} where ID = #{id,jdbcType=INTEGER} ===== PermissionMapper.xml ===== ID, PERMISSION delete from permission where ID = #{id,jdbcType=INTEGER} insert into permission (ID, PERMISSION) values (#{id,jdbcType=INTEGER}, #{permission,jdbcType=VARCHAR}) insert into permission ID, PERMISSION, #{id,jdbcType=INTEGER}, #{permission,jdbcType=VARCHAR}, update permission PERMISSION = #{permission,jdbcType=VARCHAR}, where ID = #{id,jdbcType=INTEGER} update permission set PERMISSION = #{permission,jdbcType=VARCHAR} where ID = #{id,jdbcType=INTEGER} ===== RolePermissionMapper.xml ===== ID, ROLE_ID, PERMISSION_ID delete from role_permission where ID = #{id,jdbcType=INTEGER} insert into role_permission (ID, ROLE_ID, PERMISSION_ID ) values (#{id,jdbcType=INTEGER}, #{roleId,jdbcType=INTEGER}, #{permissionId,jdbcType=INTEGER} ) insert into role_permission ID, ROLE_ID, PERMISSION_ID, #{id,jdbcType=INTEGER}, #{roleId,jdbcType=INTEGER}, #{permissionId,jdbcType=INTEGER}, update role_permission ROLE_ID = #{roleId,jdbcType=INTEGER}, PERMISSION_ID = #{permissionId,jdbcType=INTEGER}, where ID = #{id,jdbcType=INTEGER} update role_permission set ROLE_ID = #{roleId,jdbcType=INTEGER}, PERMISSION_ID = #{permissionId,jdbcType=INTEGER} where ID = #{id,jdbcType=INTEGER} ===== login.ftl ===== 登录页面
用户名:
密码:
===== index.ftl ===== 登录后首页 登录成功! ===== unauthorized.ftl ===== 无权限首页 您无该权限! ===== manage.sql ===== create database manage; use manage; CREATE TABLE `user` ( `ID` int(10) unsigned NOT NULL auto_increment, `NAME` varchar(45) NOT NULL, `PASSWORD` varchar(45) NOT NULL, `CREATE_DATE` varchar(8) NOT NULL, `CREATE_TIME` varchar(6) NOT NULL, PRIMARY KEY USING BTREE (`ID`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='用户表'; CREATE TABLE `role` ( `ID` int(10) unsigned NOT NULL auto_increment, `ROLE` varchar(45) NOT NULL, PRIMARY KEY USING BTREE (`ID`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='角色表'; CREATE TABLE `user_role` ( `ID` int(10) unsigned NOT NULL auto_increment, `USER_ID` int(10) unsigned NOT NULL, `ROLE_ID` int(10) unsigned NOT NULL, PRIMARY KEY USING BTREE (`ID`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='用户角色表'; CREATE TABLE `permission` ( `ID` int(10) unsigned NOT NULL auto_increment, `PERMISSION` varchar(100) NOT NULL, PRIMARY KEY USING BTREE (`ID`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='权限表'; CREATE TABLE `role_permission` ( `ID` int(10) unsigned NOT NULL auto_increment, `ROLE_ID` int(10) unsigned NOT NULL, `PERMISSION_ID` int(10) unsigned NOT NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='角色权限表'; ===== 数据库数据截图 ===== {{:分享:技术:shiro:user.png?600|}} {{:分享:技术:shiro:role.png?300|}} {{:分享:技术:shiro:user_role.png?300|}} {{:分享:技术:shiro:permission.png?300|}} {{:分享:技术:shiro:role_permission.png?300|}}