用户权限,url拦截,这在系统开发是不可少的,也是很重要的一环。有时候,我们可能在页面隐藏掉某些功能,但是,一旦我们直接通过url访问,或者自己写代码去访问的时候,如果没有权限的控制,那么我们的私有数据将暴露。知道了其重要性,那么该怎么去实现一个管理url方便,且安全的权限系统呢。
其实现在市场上提供了很多第三方的安全框架,例如spring security,shrio。这些在工作中都是使用非常普遍的,又或者自己在spring mvc或者Struct框架中,使用拦截器去实现。又或者最原始的servlet中的拦截器。实现的方式有很多种,但是原理都是一样的。
而且最最常见的无非得经过三个过滤:
1.访问的url是否合法(带参的检查)
2.是否登录
3.是否对当前url拥有权限
第一步可要可不要。但是是否登录,是否对当前url拥有权限,则是必要的。
一般普遍且简单的权限系统,表设计:
1.用户表
2.角色表
3.url资源表
4.用户---角色表 (多对多)
5.角色---url资源表 (多对多)
现在不谈实现,先谈原理,走一遍流程:
用户登录------根据输入用户id拿用户整一条数据------如果拿不到,那么返回错误说该用户不存在,如果拿到了用户数据,比对输入的密码,比对是否过期等用户自定义的条件,比对正确,那么成功登录。若不正确,则返回错误的信息。若正确后,那么可以在request中拿到用户登录的日志,写进数据库。将用户数据存储到session中(或者自己使用redis搭建的缓存,这其实类似session)。成功登录以后,将会立刻跳转到主页url。此时此请求将要走权限系统了。
首先得判断是否登录了,如果session中有这个用户的数据,那么证明登录了,走过登录验证后,将走权限验证:根据url去找角色,根据用户去找角色,如果两者有共同角色,那么证明该用户拥有该url的权限。
整个流程就是这样了。
如何用代码去实现呢?
在spring mvc框架下,我总结两种流行的实现方式:
自己使用spring mvc提供的拦截器去实现:
首先springmvc配置文件配置:
这个配置的意思是:对/androidpublic/*.do /Ad**/**/*.do的请求进行拦截,对/androidpublic/alogin.do /androidpublic/logout.do忽略掉。
然后拦截器是:
com.app.zf.itsm.android.publics.interceptor.AdLoginHandlerIntercep
这是我一个项目里安卓服务端的拦截器:
public class AdLoginHandlerIntercep extends HandlerInterceptorAdapter{
/**autor:cwy
* 00表示不是最初来源,01代表尚未登录。将登陆验证和url权限验证写在一起
* 说明:首先验证登录,在登录的基础上验证来源是否正确,最后验证是否有权限
* 权限验证这里有三种情况是不拦截的:1.url池里一个url都没有,2.url没有录入进资源管理或者,url没有一个宿主,3。url录入,且有宿主,但是另外的宿主没有分配权限
* 注意事项:一旦一个url录入进资源管理,必须先给他一个宿主(系统管理员),否则,所有人都可以访问这个url
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
PageData pd = new PageData();
pd=new PageData(request);
String token1=request.getParameter("TOKEN1");
String orgin=request.getParameter("ORIGIN");
String path=request.getRequestURI();
if(StringUtils.isNotEmpty(RedisPool.get(token1)))
{
if(StringUtils.isNotEmpty(request.getParameter("INFOR"))) //已登录,还需要验证签名(签名存在)
{
String token2=RedisPool.get(token1); //获得真正的token
String origin = MD5.md5(path+"?"+token2+orgin); //获取token和url的MD5加密
if(!origin.equals(pd.get("INFOR"))) //对比签名,防止url被人拦截后,模拟发送请求
{
response.getWriter().print(InterceptorStatusConstant.NO_ORGIN); //不是最初来源
return false;
}
else
{
//已登录,签名通过,还需要验证是否对url有访问权限
String url=request.getServletPath();
//找到所有的url
List allUrlList = MemeryCacheManager.getResourceRoleCache().getList("ALL_URL_LIST", String.class); // 从缓存中读取系统中所有url集合,进行对比
if (CollectionUtils.isEmpty(allUrlList)) {
SysResourceService resourceService = (SysResourceService) SpringContextUtil.getBean("sysresourceservice");
allUrlList = resourceService.findAllUrl();
}
if (CollectionUtils.isNotEmpty(allUrlList)) { //若数据库存在url,且找不到url与请求的url相同,那么将不拦截;如果有相同,在验证是否url对应的角色与用户拥有的角色是否相同,相同则不拦截,不相同则拦截,如果对应的url对应的角色为null,则不拦截。
for (String resURL : allUrlList) {
if (StringUtils.startsWith(url, resURL)) {
List atts = MemeryCacheManager.getResourceRoleCache().getList(resURL, ConfigAttribute.class); // 从缓存读取对应请求url,所包含的角色集合
if (CollectionUtils.isEmpty(atts)) {
SysResourceService resourceService = (SysResourceService) SpringContextUtil.getBean("sysresourceservice");
atts = resourceService.findConfigAttByURL(resURL); //通过url找url对应的角色,若找到了,执行下一步,找不到的话,代表url没有宿主,所以这个url可以被所有的用户访问
}
if (CollectionUtils.isNotEmpty(atts)) {
Iterator ite = atts.iterator(); // 请求URL所对应的角色集合
while (ite.hasNext()) {
ConfigAttribute ca = ite.next();
String needRole = ((SecurityConfig) ca).getAttribute();
//从redis缓存中拿用户角色代码字符串,并转化成数组
JSONArray relecodesJson=JSON.parseArray(RedisPublicInforUtil.getRolesCodes(request));
Object rolecodes[]= relecodesJson.toArray();
for (int i=0;i
spring security 在市场上还是很受欢迎的。它的功能很强大,不仅仅是拦截,还提供单点登录,即后一个用户登录会挤掉前一个登录的用户(这是可配置的)。
来自当前正在开发的系统的一个spring security配置文件:
org.springframework.security.messages
系统登录
验证码:
yes
211,211,211
47,79,79
23
75
24
1234567890
4
新宋体
white
com.google.code.kaptcha.impl.NoNoise
com.google.code.kaptcha.impl.ShadowGimpy
@Override
public UserDetails loadUserByUsername(String arg0)
throws UsernameNotFoundException {
// TODO Auto-generated method stub
return null;
}
arg0代表的其实就是账号。这个方法里面需要放置的逻辑是:根据账号拿用户信息,包括基本信息和额外需要用到的信息,例如用户拥有的角色,用户所在的数据域等等,然后将其返回。框架会自动帮助我们去判断密码,账号是否到期等等。
一个实现实例:
用户实体类需要实现框架的UserDetails接口:这个接口是
public class SysUser extends BaseEntity implements UserDetails, Serializable {
@Override
public Collection extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getPassword() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getUsername() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isAccountNonExpired() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return false;
}
}
public class SysUser extends BaseEntity implements UserDetails, Serializable {
private static final String mgrAccount = "admin";//系统管理员
private static final long serialVersionUID = 1L;
private String username; // 名称
private String sex; // 性别
private String loginId; // 登陆账号
private String password; // 密码
private String enName; // 英文名
private String employeeId; // 员工ID
private String post; // 岗位
private String duty; // 职务
private String email; // 邮箱
private String qq;
private String mobile; // 手机
private String officePhone; // 办公电话
private String dutyDesc; // 职责
private String headImage; // 头像地址
private Date birthday; // 生日
private Date joinDate; // 入职日期
private Date expiredDate; // 合同到期日期
private String stateFlag; // 状态 1:在职,2:离职,3:待定
private String showState; // 隐藏状态 y:显示,h:隐藏
private String deleteFlag; // n:未删除
private Integer orderBy; // 排序
private String remark; // 备注
private String companyId; // 公司ID
private String phonecode; //手机唯一码
@Transient
public String getPhonecode() {
return phonecode;
}
@Transient
public void setPhonecode(String phonecode) {
this.phonecode = phonecode;
}
// 临时
private String birthdayFmt; // 格式化
private String joinDateFmt; // 格式化
private String expiredDateFmt; // 格式化
private String expiredState; // 过期状态
private String companyName; // 公司名称
private String companyCode; // 公司编码
private String companyType; // 公司类型
private String orgId; // 组织ID
private String orgName; // 组织名称
private String parentOrgIds; // 父辈组织ID
private String parentOrgNames; // 父辈组织
private String virtualOrgId; // 虚拟组织ID
private String virtualOrgName; // 虚拟组织名称
private String postName; // 岗位名称
private String dutyName; // 职务名称
private String roleId; // 角色ID
private boolean isManage; // 是否系统管理机构,属于该组织下的人员拥有查看全部数据权限
private List roles; // 拥有的角色集合
private List authlist = new ArrayList(); // spring_security验证角色编码
List companyList; // 关联公司或服务商
List userGroupList; // 所属班组
private Date dutywatchadate; //排班的值班日期
public SysUser() {
}
public SysUser(String resourceid, String username) {
super();
setResourceid(resourceid);
this.username = username;
}
@Column(name = "USERNAME", length = 50)
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
@Column(name = "SEX", length = 50)
public String getSex() {
return this.sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Column(name = "LOGIN_ID", length = 50)
public String getLoginId() {
return this.loginId;
}
public void setLoginId(String loginId) {
this.loginId = loginId;
}
@Column(name = "PASSWORD", length = 32)
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
@Column(name = "EN_NAME", length = 50)
public String getEnName() {
return this.enName;
}
public void setEnName(String enName) {
this.enName = enName;
}
@Column(name = "EMPLOYEE_ID", length = 50)
public String getEmployeeId() {
return this.employeeId;
}
public void setEmployeeId(String employeeId) {
this.employeeId = employeeId;
}
@Column(name = "POST", length = 50)
public String getPost() {
return this.post;
}
public void setPost(String post) {
this.post = post;
}
@Column(name = "DUTY", length = 50)
public String getDuty() {
return duty;
}
public void setDuty(String duty) {
this.duty = duty;
}
@Column(name = "EMAIL", length = 100)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Column(name = "QQ", length = 50)
public String getQq() {
return this.qq;
}
public void setQq(String qq) {
this.qq = qq;
}
@Column(name = "MOBILE", length = 100)
public String getMobile() {
return this.mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
@Column(name = "OFFICE_PHONE", length = 100)
public String getOfficePhone() {
return this.officePhone;
}
public void setOfficePhone(String officePhone) {
this.officePhone = officePhone;
}
@Column(name = "DUTY_DESC", length = 650)
public String getDutyDesc() {
return this.dutyDesc;
}
public void setDutyDesc(String dutyDesc) {
this.dutyDesc = dutyDesc;
}
@Column(name = "HEAD_IMAGE", length = 150)
public String getHeadImage() {
return this.headImage;
}
public void setHeadImage(String headImage) {
this.headImage = headImage;
}
@Temporal(TemporalType.DATE)
@Column(name = "BIRTHDAY")
public Date getBirthday() {
return this.birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
birthdayFmt = birthday != null ? DateTimeUtil.formatDate(birthday) : "";
}
@Temporal(TemporalType.DATE)
@Column(name = "JOIN_DATE")
public Date getJoinDate() {
return this.joinDate;
}
public void setJoinDate(Date joinDate) {
this.joinDate = joinDate;
joinDateFmt = joinDate != null ? DateTimeUtil.formatDate(joinDate) : "";
}
@Temporal(TemporalType.DATE)
@Column(name = "EXPIRED_DATE")
public Date getExpiredDate() {
return expiredDate;
}
private boolean expiredBool = true; // 过期标志:默认有效
public void setExpiredDate(Date expiredDate) {
this.expiredDate = expiredDate;
expiredDateFmt = expiredDate != null ? DateTimeUtil.formatDate(expiredDate) : "";
if (null == expiredDate) {
setExpiredState("长期");
} else {
if (DateTimeUtil.addDays(expiredDate, 1).compareTo(new Date()) < 0) { // 合同到期时间小与当前时间,账号过期
setExpiredState("过期");
expiredBool = false;
} else {
setExpiredState("有效");
}
}
}
@Column(name = "STATE_FLAG", length = 1)
public String getStateFlag() {
return stateFlag;
}
public void setStateFlag(String stateFlag) {
this.stateFlag = stateFlag;
}
@Column(name = "SHOW_STATE", length = 1)
public String getShowState() {
return showState;
}
public void setShowState(String showState) {
this.showState = showState;
}
@Column(name = "DELETE_FLAG", length = 1)
public String getDeleteFlag() {
return deleteFlag;
}
public void setDeleteFlag(String deleteFlag) {
this.deleteFlag = deleteFlag;
}
@Column(name = "ORDER_BY")
public Integer getOrderBy() {
return this.orderBy;
}
public void setOrderBy(Integer orderBy) {
this.orderBy = orderBy;
}
@Column(name = "REMARK", length = 500)
public String getRemark() {
return this.remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
@Column(name = "COMPANY_ID")
public String getCompanyId() {
return companyId;
}
public void setCompanyId(String companyId) {
this.companyId = companyId;
}
/**
* 是否系统管理机构,属于该组织下的人员拥有查看全部数据权限
*
* @return true:是(查看全部数据)、false:否(只能查看本公司数据)
*/
@Transient
public boolean isManage() {
if(isManage && mgrAccount.equals(this.getLoginId())){
return true;
}else{
return false;
}
}
public void setManage(boolean isManage) {
this.isManage = isManage;
}
@Transient
public List getRoles() {
return roles;
}
public void setRoles(List roles) {
this.roles = roles;
// 组装用户拥有角色成spring security验证
if (roles != null && roles.size() > 0) {
for (SysRole role : roles) {
authlist.add(new SimpleGrantedAuthority(role.getRoleCode()));
}
}
}
/**
* 过期标志
*/
@Transient
public boolean isAccountNonExpired() {
return expiredBool;
}
/**
* 锁定标志,在职状态才能进入系统
*/
@Transient
public boolean isAccountNonLocked() {
return StringUtils.equalsIgnoreCase(stateFlag, "1") ? true : false;
}
@Transient
public boolean isCredentialsNonExpired() {
return true;
}
@Transient
public boolean isEnabled() {
return true;
}
// 重写equals与hashCode,判断用户相等
public boolean equals(Object rhs) {
if (!(rhs instanceof SysUser) || (rhs == null)) {
return false;
}
SysUser user = (SysUser) rhs;
return (this.getPassword().equals(user.getPassword()) && this.getUsername().equals(user.getUsername()) && (this.isAccountNonExpired() == user.isAccountNonExpired())
&& (this.isAccountNonLocked() == user.isAccountNonLocked()) && (this.isCredentialsNonExpired() == user.isCredentialsNonExpired()) && (this.isEnabled() == user.isEnabled()));
}
public int hashCode() {
int code = 9792;
for (GrantedAuthority authority : getAuthorities()) {
code = code * (authority.hashCode() % 7);
}
if (this.getPassword() != null) {
code = code * (this.getPassword().hashCode() % 7);
}
if (this.getUsername() != null) {
code = code * (this.getUsername().hashCode() % 7);
}
if (this.isAccountNonExpired()) {
code = code * -2;
}
if (this.isAccountNonLocked()) {
code = code * -3;
}
if (this.isCredentialsNonExpired()) {
code = code * -5;
}
if (this.isEnabled()) {
code = code * -7;
}
return code;
}
// 组装用户拥有角色成spring security验证
@Transient
public Collection extends GrantedAuthority> getAuthorities() {
return authlist;
}
@Transient
public String getRoleId() {
return roleId;
}
public void setRoleId(String roleId) {
this.roleId = roleId;
}
@Transient
public String getOrgId() {
return orgId;
}
public void setOrgId(String orgId) {
this.orgId = orgId;
}
@Transient
public String getOrgName() {
return orgName;
}
public void setOrgName(String orgName) {
this.orgName = orgName;
}
@Transient
public String getParentOrgIds() {
return parentOrgIds;
}
public void setParentOrgIds(String parentOrgIds) {
this.parentOrgIds = parentOrgIds;
}
@Transient
public String getParentOrgNames() {
return parentOrgNames;
}
public void setParentOrgNames(String parentOrgNames) {
this.parentOrgNames = parentOrgNames;
}
@Transient
public String getVirtualOrgId() {
return virtualOrgId;
}
public void setVirtualOrgId(String virtualOrgId) {
this.virtualOrgId = virtualOrgId;
}
@Transient
public String getVirtualOrgName() {
return virtualOrgName;
}
public void setVirtualOrgName(String virtualOrgName) {
this.virtualOrgName = virtualOrgName;
}
@Transient
public String getPostName() {
return postName;
}
public void setPostName(String postName) {
this.postName = postName;
}
@Transient
public String getBirthdayFmt() {
return birthdayFmt;
}
public void setBirthdayFmt(String birthdayFmt) {
this.birthdayFmt = birthdayFmt;
}
@Transient
public String getJoinDateFmt() {
return joinDateFmt;
}
public void setJoinDateFmt(String joinDateFmt) {
this.joinDateFmt = joinDateFmt;
}
@Transient
public String getExpiredDateFmt() {
return expiredDateFmt;
}
public void setExpiredDateFmt(String expiredDateFmt) {
this.expiredDateFmt = expiredDateFmt;
}
@Transient
public String getExpiredState() {
return expiredState;
}
public void setExpiredState(String expiredState) {
this.expiredState = expiredState;
}
@Transient
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
@Transient
public String getCompanyCode() {
return companyCode;
}
public void setCompanyCode(String companyCode) {
this.companyCode = companyCode;
String manageOrg = PropertiesUtil.get("SYS_MANAGE"); // 系统管理机构编码
if (StringUtils.equals(companyCode, manageOrg))
setManage(true);
}
@Transient
public String getCompanyType() {
return companyType;
}
public void setCompanyType(String companyType) {
this.companyType = companyType;
}
@Transient
public List getCompanyList() {
return companyList;
}
public void setCompanyList(List companyList) {
this.companyList = companyList;
}
@Transient
public List getUserGroupList() {
return userGroupList;
}
public void setUserGroupList(List userGroupList) {
this.userGroupList = userGroupList;
}
@Transient
@Temporal(TemporalType.DATE)
public Date getDutywatchadate() {
return dutywatchadate;
}
public void setDutywatchadate(Date dutywatchadate) {
this.dutywatchadate = dutywatchadate;
}
@Transient
public String getDutyName() {
return dutyName;
}
public void setDutyName(String dutyName) {
this.dutyName = dutyName;
}
}
用户登录将走到这里来
public class MyUserDetailService implements UserDetailsService {
private static Logger logger = LogManager.getLogger(MyUserDetailService.class);
// 注入服务
SysUserService sysUserService;
SysOrganizationService sysOrganizationService;
SysUserLoginLogService sysUserLoginLogService;
@Autowired
SysUserGroupService sysUserGroupService;
public SysUser loadUserByUsername(String loginId) throws UsernameNotFoundException, DataAccessException {
SysUser loginUser = new SysUser(); // 登录用户
if (StringUtils.isNotEmpty(loginId)) {
logger.info(loginId + " LOGIN...");
loginUser = sysUserService.findUserByLoginId(loginId); // 通过loginId查询用户
if (null != loginUser) {
loginUser.setPostName(DictionaryELTag.getTextByCompanyId("D_Post", loginUser.getPost(),loginUser.getCompanyId()));
// 查询用户拥有角色
List roles = sysUserService.findSysRoleByUserId(loginUser.getResourceid());
if (CollectionUtils.isNotEmpty(roles)){
loginUser.setRoles(roles);
}
if (StringUtils.equals(loginUser.getCompanyType(), "1")) { // 1:公司
List companyList = sysOrganizationService.findCompanyByType("2", loginUser.getCompanyId());
loginUser.setCompanyList(companyList);
} else if (StringUtils.equals(loginUser.getCompanyType(), "2")) { // 2:服务商
List companyList = sysOrganizationService.findCompanyByType("1", loginUser.getCompanyId());
loginUser.setCompanyList(companyList);
}
//查询所在班组(list)
List groupList = sysUserGroupService.getUserGroupByUserid(loginUser.getResourceid());
if (CollectionUtils.isNotEmpty(groupList)){
loginUser.setUserGroupList(groupList);
}
} else {
logger.info("用户名(" + loginId + ")不存在...");
throw new UsernameNotFoundException("用户名(" + loginId + ")不存在...");
}
} else {
throw new UsernameNotFoundException("用户名不能为空...");
}
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String agent = request.getHeader("User-Agent").toUpperCase(); // 浏览器类型
String screen_height = request.getParameter("screen_height"); // 分辨率高
String screen_width = request.getParameter("screen_width"); // 分辨率宽
String ip = getIpAddr(request);
SysUserLoginLog loginLog = new SysUserLoginLog(loginUser.getResourceid(), loginUser.getUsername(), ip, agent, screen_height, screen_width, loginUser.getCompanyId());
sysUserLoginLogService.save(loginLog); // 保存登录日志
logger.info(loginId + " SUCCESS LOGIN...IP:" + ip);
return loginUser;
}
/**
* 通过HttpServletRequest返回IP地址
*
* @param request
* HttpServletRequest
* @return ip String
*/
public String getIpAddr(HttpServletRequest request) throws RuntimeException {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
if (ip == null && ("0:0:0:0:0:0:0:1").equals(ip))
ip = "127.0.0.1";
return ip;
}
public SysUserService getSysUserService() {
return sysUserService;
}
public void setSysUserService(SysUserService sysUserService) {
this.sysUserService = sysUserService;
}
public SysOrganizationService getSysOrganizationService() {
return sysOrganizationService;
}
public void setSysOrganizationService(SysOrganizationService sysOrganizationService) {
this.sysOrganizationService = sysOrganizationService;
}
public SysUserLoginLogService getSysUserLoginLogService() {
return sysUserLoginLogService;
}
public void setSysUserLoginLogService(SysUserLoginLogService sysUserLoginLogService) {
this.sysUserLoginLogService = sysUserLoginLogService;
}
}
登录成功后访问一个url:
走拦截器:
/**
* TODO:1、拦截器
*/
public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
private FilterInvocationSecurityMetadataSource securityMetadataSource;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
FilterInvocation fi = new FilterInvocation(request, response, chain);
invoke(fi);
}
public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
return this.securityMetadataSource;
}
public Class extends Object> getSecureObjectClass() {
return FilterInvocation.class;
}
public void invoke(FilterInvocation fi) throws IOException, ServletException {
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
super.afterInvocation(token, null);
}
}
public SecurityMetadataSource obtainSecurityMetadataSource() {
return this.securityMetadataSource;
}
public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource newSource) {
this.securityMetadataSource = newSource;
}
public void destroy() {
}
public void init(FilterConfig arg0) throws ServletException {
}
}
public class MyInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
private static Logger logger = LogManager.getLogger(MyInvocationSecurityMetadataSource.class);
public MyInvocationSecurityMetadataSource() {
logger.debug("===============================初始化=================================");
}
public Collection getAttributes(Object object) throws IllegalArgumentException {
String url = ((FilterInvocation) object).getRequestUrl(); // 请求地址
List allUrlList = MemeryCacheManager.getResourceRoleCache().getList("ALL_URL_LIST", String.class); // 从缓存中读取系统中所有url集合,进行对比
if (CollectionUtils.isEmpty(allUrlList)) {
SysResourceService resourceService = (SysResourceService) SpringContextUtil.getBean("sysresourceservice");
allUrlList = resourceService.findAllUrl();
}
logger.info((SpringContextUtil.getUser() != null ? "USER:" + SpringContextUtil.getUser().getUsername():"用户没登陆") + " ACCESS_URL:" + url);
if (CollectionUtils.isNotEmpty(allUrlList)) {
for (String resURL : allUrlList) {
if (StringUtils.startsWith(url, resURL)) {
List atts = MemeryCacheManager.getResourceRoleCache().getList(resURL, ConfigAttribute.class); // 从缓存读取对应请求url,所包含的角色集合
if (CollectionUtils.isEmpty(atts)) {
SysResourceService resourceService = (SysResourceService) SpringContextUtil.getBean("sysresourceservice");
atts = resourceService.findConfigAttByURL(resURL);
}
if (CollectionUtils.isNotEmpty(atts)) {
return atts;
} else {
return null;
}
}
} // end for
}
return null;
}
public boolean supports(Class> clazz) {
return true;
}
public Collection getAllConfigAttributes() {
return null;
}
}
若url对应的就是为null,则所有人都可以访问,否则返回角色的集合,到第三阶段:权限和是否登录的拦截:
public class MyAccessDecisionManager implements AccessDecisionManager {
/**
* 根据用户的角色与URL拥有的角色对比,以确认是否有权限 authentication:访问者所拥有的角色 object:请求URL
* configAttributes:请求资源所拥有的角色
* 说明:如果在资源管理那边新增了一个url,那么务必给这个url分配一个宿主,否则,所有人(对这个资源无权限的用户)也可以访问
*/
public void decide(Authentication authentication, Object object, Collection configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
if (configAttributes == null) //请求资源拥有的角色为null时,所有人都可以去访问这个资源
{
return;
}
// HttpServletRequest request = invocation.getHttpRequest();
Object obj = authentication.getPrincipal();
if (obj.toString().equals("anonymousUser")) {
FilterInvocation invocation = (FilterInvocation) object;
String fullUrl = invocation.getFullRequestUrl(); // 外部访问全地址
String basePath = PropertiesUtil.get("SYS_BASE_PATH");
if (StringUtils.startsWithIgnoreCase(fullUrl, basePath)) // 外部访问
return;
}
Iterator ite = configAttributes.iterator(); // 请求URL所对应的角色集合
while (ite.hasNext()) {
ConfigAttribute ca = ite.next();
String needRole = ((SecurityConfig) ca).getAttribute();
for (GrantedAuthority ga : authentication.getAuthorities()) { // 用户所拥有角色
if (StringUtils.equals(StringUtils.trim(needRole), StringUtils.trim(ga.getAuthority()))) {
return;
}
}
}
throw new AccessDeniedException("请求失败,请检查您的权限...");
}
public boolean supports(ConfigAttribute configattribute) {
return true;
}
public boolean supports(Class> class1) {
return true;
}
}
本文完毕。