SpringSecurity 3.2入门(9)自定义权限控制代码实现
1、 一个自定义的filter,必须包含authenticationManager,accessDecisionManager,securityMetadataSource三个属性,我们的所有控制将在这三个类中实现 。
package cn.jxufe.core.security; import java.io.IOException; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; public class MySecurityFilter extends AbstractSecurityInterceptor implements
Filter { protected Logger logger = LoggerFactory.getLogger(getClass()); // 与applicationContext-security.xml里的myFilter的属性securityMetadataSource对应,
// 其他的两个组件,已经在AbstractSecurityInterceptor定义
private FilterInvocationSecurityMetadataSource securityMetadataSource; @Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
return this.securityMetadataSource;
} public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
logger.debug("------------MyFilterSecurityInterceptor.doFilter()-----------开始拦截了....");
FilterInvocation fi = new FilterInvocation(request, response, chain);
invoke(fi);
} private void invoke(FilterInvocation fi) throws IOException,
ServletException {
// object为FilterInvocation对象
// 1.获取请求资源的权限
// 执行Collection<ConfigAttribute> attributes =
// SecurityMetadataSource.getAttributes(object); logger.debug("--------------用户发送请求--------------");
InterceptorStatusToken token = null;
token = super.beforeInvocation(fi);
try {
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
}catch (Exception e) {
}finally {
super.afterInvocation(token, null);
} logger.debug("------------MyFilterSecurityInterceptor.doFilter()-----------拦截结束了....");
} public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
return securityMetadataSource;
} public void setSecurityMetadataSource(
FilterInvocationSecurityMetadataSource securityMetadataSource) {
this.securityMetadataSource = securityMetadataSource;
} public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
} public void destroy() {
// TODO Auto-generated method stub
} public Class<? extends Object> getSecureObjectClass() {
// 下面的MyAccessDecisionManager的supports方面必须放回true,否则会提醒类型错误
return FilterInvocation.class;
}
}
MySecurityFilter.java
2、用于启动时加载资源列表,还拥有判断是否拥有请求访问资源权限的方法。
package cn.jxufe.core.security; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.util.AntPathMatcher; import cn.jxufe.core.dao.BaseDao;
import cn.jxufe.core.entiry.Resource;
import cn.jxufe.core.entiry.Role; public class MyFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource { protected Logger logger = LoggerFactory.getLogger(getClass()); private AntPathMatcher urlMatcher = new AntPathMatcher(); private static Map<String, Collection<ConfigAttribute>> resourceMap = null; private BaseDao baseDao; public BaseDao getBaseDao() {
return baseDao;
} public void setBaseDao(BaseDao baseDao) {
this.baseDao = baseDao;
} //由spring调用
public MyFilterInvocationSecurityMetadataSource(BaseDao baseDao) {
this.baseDao=baseDao;
loadResourceDefine();
} //加载所有资源
private void loadResourceDefine() {
logger.debug("容器启动(MySecurityMetadataSource:loadResourceDefine)");
logger.debug("--------------开始加载系统资源与权限列表数据--------------");
resourceMap = new HashMap<String,Collection<ConfigAttribute>>();
String sql="select * from t_system_resource_info";
List<Resource> resources = this.baseDao.findListBeanByArray(sql, Resource.class);
for(Resource resource : resources){
Collection<ConfigAttribute> configAttributes = null;
ConfigAttribute configAttribute = new SecurityConfig(resource.getName());
if(resourceMap.containsKey(resource.getPath())){
configAttributes = resourceMap.get(resource.getPath());
configAttributes.add(configAttribute);
}else{
configAttributes = new ArrayList<ConfigAttribute>() ;
configAttributes.add(configAttribute);
resourceMap.put(resource.getPath(), configAttributes);
}
}
logger.debug("--------------系统资源与权限列表数据加载结束--------------");
} /**
* 根据请求的资源地址,获取它所拥有的权限
*/
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
//获取请求的url地址
String requestUrl = ((FilterInvocation) object).getRequestUrl();
logger.debug("--------------取得请求资源所需权限(MySecurityMetadataSource:getAttributes)--------------");
logger.debug("--------------请求地址为:"+requestUrl+"--------------");
Iterator<String> it = resourceMap.keySet().iterator();
while(it.hasNext()){
String _url = it.next();
if(_url.indexOf("?")!=-1){
_url = _url.substring(0, _url.indexOf("?"));
}
if(urlMatcher.match(_url,requestUrl))
return resourceMap.get(_url);
}
return null; //如果是想做到没配的资源默认可以访问的话,那么就返回空或者NULL /**
* 使用下面的写法代替return null;没配的资源则不可以访问,建议开发的时候还是用上面的为好。
*/
// Collection<ConfigAttribute> returnCollection = new ArrayList<ConfigAttribute>();
// returnCollection.add(new SecurityConfig("ROLE_NO_USER"));
// return returnCollection;
} public Collection<ConfigAttribute> getAllConfigAttributes() {
Set<ConfigAttribute> allAttributes = new HashSet<ConfigAttribute>();
for (Entry<String, Collection<ConfigAttribute>> entry : resourceMap.entrySet()) {
allAttributes.addAll(entry.getValue());
}
logger.debug(allAttributes.toString());
return allAttributes;
} public Collection<ConfigAttribute> getConfigAttributes(String...value) {
return SecurityConfig.createList(value);
} public boolean supports(Class<?> clazz) {
return true;
} }
MyFilterInvocationSecurityMetadataSource.java
3、访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源 ;做最终的访问控制决定。
package cn.jxufe.core.security; import java.util.Collection;
import java.util.Iterator; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority; public class MyAccessDecisionManager implements AccessDecisionManager { protected Logger logger = LoggerFactory.getLogger(getClass()); /**
* 认证用户是否具有权限访问该url地址
*
*/
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
logger.debug("--------------匹配用户拥有权限和请求权限(MyAccessDecisionManager:decide)--------------");
logger.debug("--------------验证用户是否具有一定的权限--------------");
if(configAttributes == null) {
return;
}
//所请求的资源拥有的权限(一个资源对多个权限)
Iterator<ConfigAttribute> iterator = configAttributes.iterator();
while(iterator.hasNext()) {
ConfigAttribute configAttribute = iterator.next();
//访问所请求资源所需要的权限
String needPermission = configAttribute.getAttribute();
logger.debug("--------------访问所请求资源所需要的权限为 " + needPermission+"--------------");
//用户所拥有的权限authentication
for(GrantedAuthority ga : authentication.getAuthorities()) {
if(needPermission.equals(ga.getAuthority())) {
logger.debug("--------------权限验证通过--------------");
return;
}
}
}
//没有权限让我们去捕捉
logger.debug("--------------权限验证未通过--------------");
throw new AccessDeniedException(" 没有权限访问!");
} /**
* 启动时候被AbstractSecurityInterceptor调用,决定AccessDecisionManager是否可以执行传递ConfigAttribute。
*/
public boolean supports(ConfigAttribute attribute) {
// System.out.println("MyAccessDescisionManager.supports()------------"+attribute.getAttribute());
return true;
} /**
* 被安全拦截器实现调用,包含安全拦截器将显示的AccessDecisionManager支持安全对象的类型
*/
public boolean supports(Class<?> clazz) {
logger.debug("MyAccessDescisionManager.supports()--------------------------------");
return true;
} }
MyAccessDecisionManager.java
4、验证登录信息。
package cn.jxufe.core.security; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import cn.jxufe.core.dao.BaseDao;
import cn.jxufe.core.entiry.User; public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private static final String USERNAME = "username";
private static final String PASSWORD = "password";
private static final String KAPTCHA = "kaptcha"; private BaseDao baseDao; public BaseDao getBaseDao() {
return baseDao;
} public void setBaseDao(BaseDao baseDao) {
this.baseDao = baseDao;
} @Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (!request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
} String username = obtainUsername(request);
String password = obtainPassword(request);
String kaptcha = obtainKaptcha(request);
logger.debug("--------------用户:" + username +"正在登录---"+kaptcha+"-----------");
// 验证码校验
String kaptchaExpected = (String) request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
if(!kaptcha.equals(kaptchaExpected)){
BadCredentialsException exception = new BadCredentialsException("验证码不匹配!");
throw exception;
} // 账号与密码校验
username = username.trim();
String sql="select * from t_system_user_info where username=? and password=?";
Object[] args=new Object[]{ username, password }; User users = (User) this.baseDao.findUniqueBeanByArray(sql, User.class, args);
if (users == null || !users.getPassword().equals(password)) {
BadCredentialsException exception = new BadCredentialsException("用户名或密码不匹配!");
throw exception;
}
// 实现 Authentication
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
// 允许子类设置详细属性
setDetails(request, authRequest);
// 运行UserDetailsService的loadUserByUsername 再次封装Authentication
return this.getAuthenticationManager().authenticate(authRequest);
} @Override
protected String obtainUsername(HttpServletRequest request) {
Object obj = request.getParameter(USERNAME);
return null == obj ? "" : obj.toString();
} @Override
protected String obtainPassword(HttpServletRequest request) {
Object obj = request.getParameter(PASSWORD);
return null == obj ? "" : obj.toString();
} protected String obtainKaptcha(HttpServletRequest request) {
Object obj = request.getParameter(KAPTCHA);
return null == obj ? "" : obj.toString();
} @Override
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
super.setDetails(request, authRequest);
}
}
MyUsernamePasswordAuthenticationFilter.java
5、登录成功后,根据用户名,返回一个Userdetail。
package cn.jxufe.core.security; import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component; import cn.jxufe.core.dao.BaseDao;
import cn.jxufe.core.entiry.Resource; @Component("userDetailsService")
public class MyUserDetailsService implements UserDetailsService { protected Logger logger = LoggerFactory.getLogger(getClass()); @Autowired
private JdbcTemplate jdbcTemplate; @Autowired
private BaseDao baseDao; //登录验证
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
logger.debug("------------验证并授权(MyUserDetailsServiceImpl:loadUserByUsername)------------"); // 根据用户名获取帐户和权限信息
String sql = "SELECT username,password,enabled,name rname " +
"FROM t_system_user_info u,t_system_role_info r,t_system_user_role ur " +
"WHERE u.id=ur.user_id AND r.id=ur.role_id AND username= ?";
// 如果一个用户具有多个权限,连接查询会返回一个List
List list =this.jdbcTemplate.queryForList(sql, new Object[] { username }); // 取出帐户和权限信息填充到User中返回
if (list == null || list.size() <= 0)
// spring-security定义的异常
throw new UsernameNotFoundException("用户不存在!");
// 如果用户存在
Map<String, Object> map = (Map<String, Object>) list.get(0);
// 密码
String password = (String) map.get("password");
// 帐户是否可用
boolean enabled = ((Integer) map.get("enabled") == 1);
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
// 帐户所具有的权限 Set<GrantedAuthority> authSet = new HashSet<GrantedAuthority>();
List<Resource> resources=this.getResourceByUsername(username);
logger.debug("------------用户所拥有权限------------");
for (int i=0;i<resources.size();i++) {
GrantedAuthority authority = new SimpleGrantedAuthority(resources.get(i).getName());
authSet.add(authority);
}
logger.debug("------------"+authSet.toString()+"------------");
// spring-security提供的类
User userdetail = new User(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authSet);
return userdetail; } private List<Resource> getResourceByUsername(String username){
String sql ="SELECT * FROM t_system_resource_info WHERE id IN(" +
"SELECT DISTINCT resource_id FROM t_system_authority_resource WHERE authority_id IN(" +
"SELECT authority_id FROM t_system_role_authority WHERE role_id IN(" +
"SELECT role_id FROM t_system_user_role WHERE user_id =( " +
"SELECT id FROM t_system_user_info WHERE username= ? ))))";
List<Resource> list =this.baseDao.findListBeanByArray(sql, Resource.class, new Object[] { username });
return list;
} }
MyUserDetailsService.java
6、配置信息
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd"> <!-- 配置不过滤的资源(静态资源及登录相关) -->
<security:http pattern="/**/*.css" security="none" />
<security:http pattern="/**/*.js" security="none" />
<security:http pattern="/**/*.jpg" security="none" />
<security:http pattern="/**/*.jpeg" security="none" />
<security:http pattern="/**/*.gif" security="none" />
<security:http pattern="/**/*.png" security="none" />
<security:http pattern="/favicon.ico" security="none" />
<!-- 不过滤验证码 -->
<security:http pattern="/captcha-image.htm" security="none" />
<!-- 不过滤登录页面 -->
<security:http pattern="/login.htm" security="none" />
<security:http pattern="/login.jsp" security="none" />
<!-- 不过滤首页 -->
<security:http pattern="/index.htm" security="none" />
<security:http pattern="/index.jsp" security="none" /> <!-- 配置SpringSecurity的http安全服务 -->
<!-- 使用了 use-expressions="true 则 需使用hasRole('ROLE_USER')-->
<!-- 配置了auto-config="true"loginFilter报错,如果你没有自定义的登录页面,它就会跳转到security默认的登录页面中。 -->
<security:http access-denied-page="/accessDenied.jsp" entry-point-ref="authenticationProcessingFilterEntryPoint">
<security:session-management>
<security:concurrency-control
max-sessions="1" />
</security:session-management> <!-- 检测失效的sessionId,session超时时,定位到另外一个URL -->
<security:session-management
invalid-session-url="/sessionTimeOut.jsp" /> <!-- 配置登出信息,指定退出系统后,跳转页面 -->
<security:logout logout-url="/logout"
logout-success-url="/login.htm" invalidate-session="true" /> <!-- 认证和授权 -->
<security:custom-filter ref="myLoginFilter" position="FORM_LOGIN_FILTER" />
<security:custom-filter ref="securityFilter" before="FILTER_SECURITY_INTERCEPTOR"/> </security:http> <!-- 认证管理器,配置SpringSecutiry的权限信息 -->
<security:authentication-manager>
<security:authentication-provider>
<!-- 使用数据库中的用户名和密码 -->
<security:jdbc-user-service
data-source-ref="dataSource" />
</security:authentication-provider>
</security:authentication-manager> <!-- 验证配置 , 认证管理器,实现用户认证的入口,主要实现UserDetailsService接口即可 -->
<security:authentication-manager alias="myAuthenticationManager">
<!-- 使用自己数据库中的用户和角色表,获取用户拥有的权限 -->
<security:authentication-provider
user-service-ref="myUserDetailsServiceImpl" />
</security:authentication-manager> <!-- 登录验证器 -->
<bean id="myLoginFilter"
class="cn.jxufe.core.security.MyUsernamePasswordAuthenticationFilter">
<!-- 处理登录 -->
<property name="filterProcessesUrl" value="/j_spring_security_check"></property>
<property name="usernameParameter" value="username"></property>
<property name="passwordParameter" value="password"></property>
<property name="authenticationSuccessHandler" ref="loginLogAuthenticationSuccessHandler"></property>
<property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler"></property>
<property name="authenticationManager" ref="myAuthenticationManager"></property>
<property name="baseDao" ref="baseDao"></property>
</bean> <bean id="loginLogAuthenticationSuccessHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/index.jsp"></property>
</bean>
<bean id="simpleUrlAuthenticationFailureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login.jsp"></property>
</bean> <!-- 认证过滤器 -->
<bean id="securityFilter" class="cn.jxufe.core.security.MySecurityFilter">
<!-- 用户拥有的权限 -->
<property name="authenticationManager" ref="myAuthenticationManager" />
<!-- 用户是否拥有所请求资源的权限 -->
<property name="accessDecisionManager" ref="myAccessDecisionManager" />
<!-- 资源与权限对应关系 -->
<property name="securityMetadataSource" ref="myFilterInvocationSecurityMetadataSource" />
</bean> <bean id="myUserDetailsServiceImpl" class="cn.jxufe.core.security.MyUserDetailsService" />
<bean id="myAccessDecisionManager" class="cn.jxufe.core.security.MyAccessDecisionManager"/>
<bean id="myFilterInvocationSecurityMetadataSource" class="cn.jxufe.core.security.MyFilterInvocationSecurityMetadataSource">
<constructor-arg name="baseDao" ref="baseDao" />
</bean> <bean id="baseDao" class="cn.jxufe.core.dao.BaseDaoImpl" /> <!-- 定义上下文返回的消息的国际化 -->
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename"
value="classpath:org/springframework/seurity/messages_zh_CN" />
</bean> <!-- 未登录的切入点 -->
<bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login.jsp"/>
</bean> </beans>
(详细的拦截过程将会在下一章中学习)。
SpringSecurity 3.2入门(9)自定义权限控制代码实现的更多相关文章
- springboot2.0整合springsecurity前后端分离进行自定义权限控制
在阅读本文之前可以先看看springsecurity的基本执行流程,下面我展示一些核心配置文件,后面给出完整的整合代码到git上面,有兴趣的小伙伴可以下载进行研究 使用maven工程构建项目,首先需要 ...
- android:Android 6.0权限控制代码封装
新建的Activity类可以继承这个Activity,这个类封装了关于新版的权限处理相关的代码 使用方法: package com.glsite.phone; import android.conte ...
- SpringSecurity 3.2入门(7)自定义权限控制介绍
总结Spring Security的使用方法有如下几种: 一种是全部利用配置文件,将用户.权限.资源(url)硬编码在xml文件中. 二种是用户和权限用数据库存储,而资源(url)和权限的对应关系硬编 ...
- abp vnext 开发快速入门 3 实现权限控制
上篇讲了abp vnext 实现了简单的增加操作的例子.删除更新查询基本类似,这里就不讲了,接下来说下如何实现角色权限控制. 再说之前,先说下如果想更加透彻的理解abp vnext的权限控制,最好是先 ...
- SpringSecurity 3.2入门(10)自定义权限控制认证及授权的过程
上一章的代码实现还存在一些问题,如角色表.权限表的用处没有体现出来,但是已经能完成URL拦截功能,后面将会继续完善认证及授权的过程. 认证及授权的过程如下: 1.容器启动,MyInvocationSe ...
- SpringSecurity 3.2入门(8)自定义权限控制数据库设计
; -- ---------------------------- -- Table structure for t_system_authority_info -- ---------------- ...
- 【SpringSecurity系列1】基于SpringSecurity实现前后端分离无状态Rest API的权限控制
源码传送门: https://github.com/ningzuoxin/zxning-springsecurity-demos/tree/master/01-springsecurity-state ...
- Spring Security教程之基于表达式的权限控制(九)
目录 1.1 通过表达式控制URL权限 1.2 通过表达式控制方法权限 1.2.1 使用@PreAuthorize和@PostAuthorize进行访问控制 1.2.2 ...
- django通用权限控制框架
在web项目中根据不同的用户肯定会限制其不同的权限,利用以下模块可以满足日常几乎所有的权限控制 permission_hook.py # 自定义权限控制,必须返回True/false ,True表 ...
随机推荐
- Mysql初识数据库《三》数据库概述
1 什么是数据(Data) 描述事物的符号记录称为数据,描述事物的符号既可以是数字,也可以是文字.图片,图像.声音.语言等,数据由多种表现形式,它们都可以经过数字化后存入计算机 在计算机中描述一个事物 ...
- 51 nod 1350 斐波那契表示
每一个正整数都可以表示为若干个斐波那契数的和,一个整数可能存在多种不同的表示方法,例如:14 = 13 + 1 = 8 + 5 + 1,其中13 + 1是最短的表示(只用了2个斐波那契数).定义F(n ...
- PTA数据结构之 List Leaves
Given a tree, you are supposed to list all the leaves in the order of top down, and left to right. I ...
- atp
一. 新建atp目录,该目录下包含bin(存放启动程序等).config(存放配置程序).lib(存放过程程序).logs(存放生成的日志).cases(存放用例的excel文件)五个目录,并新建一个 ...
- CentOS 6.3下Samba服务器的安装与配置【转载】
本文转载自 园友David_Tang的博客,如有侵权请联系本人及时删除,原文地址: http://www.cnblogs.com/mchina/archive/2012/12/18/2816717.h ...
- HDU6308-2018ACM暑假多校联合训练1011-Time Zone
题目大意就是给你UTC-8时区的时间 让你求对应时区的时间 哇 这个题 看似简单,但是一开始怎么都过不了啊 同学用自己写的read过了,后来看了一下各位大佬说改成分钟随便过,就随便过了 Problem ...
- ssh免密码登录、secureCRT免密码登录详解
再放一张真机实现图: 接下来就详细讲述实现细节. 实现过程中吃了不少苦头,这个不对,那个不通.好在慢慢一点点摸索出来了,经验分享在这里. 希望能终结网上ssh免密码登录,以及SecureCRT免密码登 ...
- SDUT OJ 图结构练习——最短路径 ( Floyed 算法 AND Dijkstra算法)
图结构练习——最短路径 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem ...
- JQ模拟触发事件
jQuery 事件 - trigger() 方法 jQuery 事件参考手册 实例 触发 input 元素的 select 事件: $("button").click(functi ...
- JUnit4.13环境配置
Junit 4.13环境配置 JUnit是一个强大的单元测试工具.它可以针对某一个特定类的所有方法进行精确打击.这个东西具体怎么使用,留在以后说.这次给大家说说idea下配置JUnit环境的方法. 1 ...