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)自定义权限控制代码实现的更多相关文章

  1. springboot2.0整合springsecurity前后端分离进行自定义权限控制

    在阅读本文之前可以先看看springsecurity的基本执行流程,下面我展示一些核心配置文件,后面给出完整的整合代码到git上面,有兴趣的小伙伴可以下载进行研究 使用maven工程构建项目,首先需要 ...

  2. android:Android 6.0权限控制代码封装

    新建的Activity类可以继承这个Activity,这个类封装了关于新版的权限处理相关的代码 使用方法: package com.glsite.phone; import android.conte ...

  3. SpringSecurity 3.2入门(7)自定义权限控制介绍

    总结Spring Security的使用方法有如下几种: 一种是全部利用配置文件,将用户.权限.资源(url)硬编码在xml文件中. 二种是用户和权限用数据库存储,而资源(url)和权限的对应关系硬编 ...

  4. abp vnext 开发快速入门 3 实现权限控制

    上篇讲了abp vnext 实现了简单的增加操作的例子.删除更新查询基本类似,这里就不讲了,接下来说下如何实现角色权限控制. 再说之前,先说下如果想更加透彻的理解abp vnext的权限控制,最好是先 ...

  5. SpringSecurity 3.2入门(10)自定义权限控制认证及授权的过程

    上一章的代码实现还存在一些问题,如角色表.权限表的用处没有体现出来,但是已经能完成URL拦截功能,后面将会继续完善认证及授权的过程. 认证及授权的过程如下: 1.容器启动,MyInvocationSe ...

  6. SpringSecurity 3.2入门(8)自定义权限控制数据库设计

    ; -- ---------------------------- -- Table structure for t_system_authority_info -- ---------------- ...

  7. 【SpringSecurity系列1】基于SpringSecurity实现前后端分离无状态Rest API的权限控制

    源码传送门: https://github.com/ningzuoxin/zxning-springsecurity-demos/tree/master/01-springsecurity-state ...

  8. Spring Security教程之基于表达式的权限控制(九)

    目录 1.1      通过表达式控制URL权限 1.2      通过表达式控制方法权限 1.2.1     使用@PreAuthorize和@PostAuthorize进行访问控制 1.2.2   ...

  9. django通用权限控制框架

    在web项目中根据不同的用户肯定会限制其不同的权限,利用以下模块可以满足日常几乎所有的权限控制 permission_hook.py  # 自定义权限控制,必须返回True/false  ,True表 ...

随机推荐

  1. Scrapy 增量式爬虫

    Scrapy 增量式爬虫 https://blog.csdn.net/mygodit/article/details/83931009 https://blog.csdn.net/mygodit/ar ...

  2. Google的C++代码规范

      英文版:http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml 中文版:http://zh-google-styleguide ...

  3. LoadRunner11_录制脚本时的浏览器版本

    最近在做的项目,因为浏览器类型及版本问题,浪费了很多时间,现在就此次的小折腾做一个小结,方便后期录制时选择(如果自己写脚本,那就可以完全忽略这些啦): (1)IE:win7   32位LR11.0,最 ...

  4. bzoj1565【NOI2009】植物大战僵尸(最小割)

    题目描述 Plants vs. Zombies(PVZ)是最近十分风靡的一款小游戏.Plants(植物)和Zombies(僵尸)是游戏的主角,其中Plants防守,而Zombies进攻.该款游戏包含多 ...

  5. 怎样关闭adobe reader的自动更新

    https://jingyan.baidu.com/article/1612d5004390ebe20f1eee50.html

  6. 23.3Sum(三数和为零)

    Level:   Medium 题目描述: Given an array nums of n integers, are there elements a, b, c in nums such tha ...

  7. Hibernate 环境配置和依赖添加(使用java web和普通javaSE工程)

    1.Hibernate依赖包的添加 File---->Project Structure,按照如图所示操作,导入所依赖的jar包. 2.生成hibernate.hbm.xml的配置文件 (1)点 ...

  8. Python web前端 02 CSS

    Python web前端 02 CSS 一.选择器 1.CSS的几种样式(CSS用来修饰.美化网页的) #建立模板 复制内容--->SETTING---> Editor -----> ...

  9. 打开页面时就提交,可以做一些自动登陆 还有SICLOGIN的测试代码

      <HTML> <head> <title> Untitled Document</title > (1)自动提交表单: <meta http- ...

  10. 【DP】【构造】NOIp模拟题 演讲 题解

        极其考思维的好题 题目背景 众所周知,$\mathrm{Zdrcl}$是一名天天$\mathrm{AK}$的高水平选手. 作为一民长者,为了向大家讲述自己$\mathrm{AK}$的经验,他决 ...