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|}}