【相关已翻译的本系列其他文章,点击分类里面的spring security 4】

上一篇:Spring
Security 4 整合Hibernate 实现持久化登录验证(带源码)

原文地址:http://websystique.com/spring-security/spring-security-4-method-security-using-preauthorize-postauthorize-secured-el/

本文探讨Spring Security 4 基于@PreAuthorize,
@PostAuthorize, @Secured和 Spring EL表达式的方法级的安全。

想要开启Spring方法级安全,你需要在已经添加了@Configuration注解的类上再添加@EnableGlobalMethodSecurity注解:

  1. package com.websystique.springsecurity.configuration;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  5. import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
  6. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  7. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  8. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  9. @Configuration
  10. @EnableWebSecurity
  11. @EnableGlobalMethodSecurity(prePostEnabled = true)
  12. public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  13. @Autowired
  14. public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
  15. auth.inMemoryAuthentication().withUser("bill").password("abc123").roles("USER");
  16. auth.inMemoryAuthentication().withUser("admin").password("root123").roles("ADMIN");
  17. auth.inMemoryAuthentication().withUser("dba").password("root123").roles("ADMIN","DBA");
  18. }
  19. @Override
  20. protected void configure(HttpSecurity http) throws Exception {
  21. http.authorizeRequests()
  22. .antMatchers("/", "/home").access("hasRole('USER') or hasRole('ADMIN') or hasRole('DBA')")
  23. .and().formLogin().loginPage("/login")
  24. .usernameParameter("ssoId").passwordParameter("password")
  25. .and().exceptionHandling().accessDeniedPage("/Access_Denied");
  26. }
  27. }
package com.websystique.springsecurity.configuration;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Configuration;

import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;

import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;

import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration

@EnableWebSecurity

@EnableGlobalMethodSecurity(prePostEnabled = true)

public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("bill").password("abc123").roles("USER");
auth.inMemoryAuthentication().withUser("admin").password("root123").roles("ADMIN");
auth.inMemoryAuthentication().withUser("dba").password("root123").roles("ADMIN","DBA");
} @Override
protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests()
.antMatchers("/", "/home").access("hasRole('USER') or hasRole('ADMIN') or hasRole('DBA')")
.and().formLogin().loginPage("/login")
.usernameParameter("ssoId").passwordParameter("password")
.and().exceptionHandling().accessDeniedPage("/Access_Denied");
}

}

@EnableGlobalMethodSecurity 开启Spring

Security 全局方法安全,等价的XML配置如下:

  1. <beans:beans xmlns="http://www.springframework.org/schema/security"  
  2.     xmlns:beans="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd  
  5.     http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">  
  6.         
  7.     <http auto-config="true" >  
  8.         <intercept-url pattern="/"     access="hasRole('USER') or hasRole('ADMIN') and hasRole('DBA')" />  
  9.         <intercept-url pattern="/home" access="hasRole('USER') or hasRole('ADMIN') and hasRole('DBA')" />  
  10.         <form-login  login-page="/login"  
  11.                      username-parameter="ssoId"  
  12.                      password-parameter="password"  
  13.                      authentication-failure-url="/Access_Denied" />  
  14.     </http>  
  15.        
  16.     <global-method-security pre-post-annotations="enabled"/>  
  17.    
  18.     <authentication-manager >  
  19.         <authentication-provider>  
  20.             <user-service>  
  21.                 <user name="bill"  password="abc123"  authorities="ROLE_USER" />  
  22.                 <user name="admin" password="root123" authorities="ROLE_ADMIN" />  
  23.                 <user name="dba"   password="root123" authorities="ROLE_ADMIN,ROLE_DBA" />  
  24.             </user-service>  
  25.         </authentication-provider>  
  26.     </authentication-manager>  
  27.        
  28. </beans:beans>  
<beans:beans xmlns="http://www.springframework.org/schema/security"

xmlns:beans="http://www.springframework.org/schema/beans"

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-4.1.xsd

http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">
&lt;http auto-config="true" &gt;
&lt;intercept-url pattern="/" access="hasRole('USER') or hasRole('ADMIN') and hasRole('DBA')" /&gt;
&lt;intercept-url pattern="/home" access="hasRole('USER') or hasRole('ADMIN') and hasRole('DBA')" /&gt;
&lt;form-login login-page="/login"
username-parameter="ssoId"
password-parameter="password"
authentication-failure-url="/Access_Denied" /&gt;
&lt;/http&gt; &lt;global-method-security pre-post-annotations="enabled"/&gt; &lt;authentication-manager &gt;
&lt;authentication-provider&gt;
&lt;user-service&gt;
&lt;user name="bill" password="abc123" authorities="ROLE_USER" /&gt;
&lt;user name="admin" password="root123" authorities="ROLE_ADMIN" /&gt;
&lt;user name="dba" password="root123" authorities="ROLE_ADMIN,ROLE_DBA" /&gt;
&lt;/user-service&gt;
&lt;/authentication-provider&gt;
&lt;/authentication-manager&gt;

</beans:beans>

注意: @EnableGlobalMethodSecurity 可以配置多个参数:

  • prePostEnabled :决定Spring Security的前注解是否可用 [@PreAuthorize,@PostAuthorize,..]
  • secureEnabled : 决定是否Spring Security的保障注解 [@Secured] 是否可用
  • jsr250Enabled :决定 JSR-250
    annotations
     注解[@RolesAllowed..] 是否可用.

You can enable more than one type of annotation in the same application, but only one type should be used for any interface or class as the behavior will not be well-defined otherwise. If two annotations are found which apply to a particular method, then only
one of them will be applied.

在同一个应用程序中,可以启用多个类型的注解,但是只应该设置一个注解对于行为类的接口或者类。如果将2个注解同事应用于某一特定方法,则只有其中一个将被应用。

我们将研究上面提到的前两个注解。

@Secured

此注释是用来定义业务方法的安全配置属性的列表。您可以在需要安全[角色/权限等]的方法上指定 @Secured,并且只有那些角色/权限的用户才可以调用该方法。如果有人不具备要求的角色/权限但试图调用此方法,将会抛出AccessDenied 异常。

@Secured 源于 Spring之前版本.它有一个局限就是不支持Spring EL表达式。可以看看下面的例子:

  1. package com.websystique.springsecurity.service;
  2. import org.springframework.security.access.annotation.Secured;
  3. public interface UserService {
  4. List<User> findAllUsers();
  5. @Secured("ROLE_ADMIN")
  6. void updateUser(User user);
  7. @Secured({ "ROLE_DBA", "ROLE_ADMIN" })
  8. void deleteUser();
  9. }
package com.websystique.springsecurity.service;

import org.springframework.security.access.annotation.Secured;

public interface UserService {
List&lt;User&gt; findAllUsers();

@Secured("ROLE_ADMIN")
void updateUser(User user); @Secured({ "ROLE_DBA", "ROLE_ADMIN" })
void deleteUser();

}

在上面的例子中,updateUser 方法只能被拥有ADMIN 权限的用户调用。deleteUser 方法只能够被拥有DBA 或者ADMIN 权限的用户调用。

如果有不具有声明的权限的用户调用此方法,将抛出AccessDenied异常。

如果你想指定AND(和)这个条件,我的意思说deleteUser
方法只能被同时拥有ADMIN & DBA 。但是仅仅通过使用 @Secured注解是无法实现的。

但是你可以使用Spring的新的注解@PreAuthorize/@PostAuthorize(支持Spring
EL),使得实现上面的功能成为可能,而且无限制。

@PreAuthorize / @PostAuthorize

Spring的 @PreAuthorize/@PostAuthorize 注解更适合方法级的安全,也支持Spring
表达式语言,提供了基于表达式的访问控制。

@PreAuthorize 注解适合进入方法前的权限验证, @PreAuthorize可以将登录用户的roles/permissions参数传到方法中。

@PostAuthorize 注解使用并不多,在方法执行后再进行权限验证。

所以它适合验证带有返回值的权限。Spring EL 提供 返回对象能够在表达式语言中获取返回的对象returnObject。

请参考 Common
Built-In Expressions
 获取支持的表达式.

现在言归正常,使用@PreAuthorize / @PostAuthorize注解

  1. package com.websystique.springsecurity.service;
  2. import org.springframework.security.access.prepost.PostAuthorize;
  3. import org.springframework.security.access.prepost.PreAuthorize;
  4. import com.websystique.springsecurity.model.User;
  5. public interface UserService {
  6. List<User> findAllUsers();
  7. @PostAuthorize ("returnObject.type == authentication.name")
  8. User findById(int id);
  9. @PreAuthorize("hasRole('ADMIN')")
  10. void updateUser(User user);
  11. @PreAuthorize("hasRole('ADMIN') AND hasRole('DBA')")
  12. void deleteUser(int id);
  13. }
package com.websystique.springsecurity.service;

import org.springframework.security.access.prepost.PostAuthorize;

import org.springframework.security.access.prepost.PreAuthorize; import com.websystique.springsecurity.model.User; public interface UserService {
List&lt;User&gt; findAllUsers();

@PostAuthorize ("returnObject.type == authentication.name")
User findById(int id); @PreAuthorize("hasRole('ADMIN')")
void updateUser(User user); @PreAuthorize("hasRole('ADMIN') AND hasRole('DBA')")
void deleteUser(int id);

}

由于 @PreAuthorize可以使用Spring 表达式语言, 使用EL表达式可以轻易的表示任意条件. deleteUser方法 可以被拥有ADMIN & DBA角色的用户调用 .

另外,我们增加了带有@PostAuthorize注解的findById()方法。通过@PostAuthorize注解 method(User
object)的返回值在Spring表达式语言中可以通过returnObject 来使用。在例子中我们确保登录用户只能获取他自己的用户对象。

上面就是@Secured, @PreAuthorize, @PostAuthorize 和EL的使用

下面提到的service实现, User 模型& 控制器

  1. package com.websystique.springsecurity.service;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import org.springframework.stereotype.Service;
  5. import org.springframework.transaction.annotation.Transactional;
  6. import com.websystique.springsecurity.model.User;
  7. @Service("userService")
  8. @Transactional
  9. public class UserServiceImpl implements UserService{
  10. static List<User> users = new ArrayList<User>();
  11. static{
  12. users = populateUser();
  13. }
  14. public List<User> findAllUsers(){
  15. return users;
  16. }
  17. public User findById(int id){
  18. for(User u : users){
  19. if(u.getId()==id){
  20. return u;
  21. }
  22. }
  23. return null;
  24. }
  25. public void updateUser(User user) {
  26. System.out.println("Only an Admin can Update a User");
  27. User u = findById(user.getId());
  28. users.remove(u);
  29. u.setFirstName(user.getFirstName());
  30. u.setLastName(user.getLastName());
  31. u.setType(user.getType());
  32. users.add(u);
  33. }
  34. public void deleteUser(int id){
  35. User u = findById(id);
  36. users.remove(u);
  37. }
  38. private static List<User> populateUser(){
  39. List<User> users = new ArrayList<User>();
  40. users.add(new User(1,"Sam","Disilva","admin"));
  41. users.add(new User(2,"Kevin","Brayn","admin"));
  42. users.add(new User(3,"Nina","Conor","dba"));
  43. users.add(new User(4,"Tito","Menz","dba"));
  44. return users;
  45. }
  46. }
package com.websystique.springsecurity.service;

import java.util.ArrayList;

import java.util.List; import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional; import com.websystique.springsecurity.model.User; @Service("userService")

@Transactional

public class UserServiceImpl implements UserService{
static List&lt;User&gt; users = new ArrayList&lt;User&gt;();

static{
users = populateUser();
} public List&lt;User&gt; findAllUsers(){
return users;
} public User findById(int id){
for(User u : users){
if(u.getId()==id){
return u;
}
}
return null;
} public void updateUser(User user) {
System.out.println("Only an Admin can Update a User");
User u = findById(user.getId());
users.remove(u);
u.setFirstName(user.getFirstName());
u.setLastName(user.getLastName());
u.setType(user.getType());
users.add(u);
} public void deleteUser(int id){
User u = findById(id);
users.remove(u);
} private static List&lt;User&gt; populateUser(){
List&lt;User&gt; users = new ArrayList&lt;User&gt;();
users.add(new User(1,"Sam","Disilva","admin"));
users.add(new User(2,"Kevin","Brayn","admin"));
users.add(new User(3,"Nina","Conor","dba"));
users.add(new User(4,"Tito","Menz","dba"));
return users;
}

}

  1. public class User {  
  2.    
  3.     private int id;  
  4.        
  5.     private String firstName;  
  6.        
  7.     private String lastName;  
  8.        
  9.     private String type;  
  10.    
  11. //getters/setters  
  12. }  
public class User {
private int id;

private String firstName;

private String lastName;

private String type;

//getters/setters

}

  1. package com.websystique.springsecurity.controller;  
  2.    
  3. import java.util.List;  
  4.    
  5. import javax.servlet.http.HttpServletRequest;  
  6. import javax.servlet.http.HttpServletResponse;  
  7.    
  8. import org.springframework.beans.factory.annotation.Autowired;  
  9. import org.springframework.security.core.Authentication;  
  10. import org.springframework.security.core.context.SecurityContextHolder;  
  11. import org.springframework.security.core.userdetails.UserDetails;  
  12. import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;  
  13. import org.springframework.stereotype.Controller;  
  14. import org.springframework.ui.ModelMap;  
  15. import org.springframework.web.bind.annotation.PathVariable;  
  16. import org.springframework.web.bind.annotation.RequestMapping;  
  17. import org.springframework.web.bind.annotation.RequestMethod;  
  18.    
  19. import com.websystique.springsecurity.model.User;  
  20. import com.websystique.springsecurity.service.UserService;  
  21.    
  22. @Controller  
  23. public class HelloWorldController {  
  24.    
  25.     @Autowired  
  26.     UserService service;  
  27.        
  28.     @RequestMapping(value = { "/", "/list" }, method = RequestMethod.GET)  
  29.     public String listAllUsers(ModelMap model) {  
  30.     
  31.         List<User> users = service.findAllUsers();  
  32.         model.addAttribute("users", users);  
  33.         return "allusers";  
  34.     }  
  35.        
  36.     @RequestMapping(value = { "/edit-user-{id}" }, method = RequestMethod.GET)  
  37.     public String editUser(@PathVariable int id, ModelMap model) {  
  38.         User user  = service.findById(id);  
  39.         model.addAttribute("user", user);  
  40.         model.addAttribute("edit", true);  
  41.         return "registration";  
  42.     }  
  43.        
  44.     @RequestMapping(value = { "/edit-user-{id}" }, method = RequestMethod.POST)  
  45.     public String updateUser(User user, ModelMap model, @PathVariable int id) {  
  46.         service.updateUser(user);  
  47.         model.addAttribute("success", "User " + user.getFirstName()  + " updated successfully");  
  48.         return "success";  
  49.     }  
  50.        
  51.     @RequestMapping(value = { "/delete-user-{id}" }, method = RequestMethod.GET)  
  52.     public String deleteUser(@PathVariable int id) {  
  53.         service.deleteUser(id);  
  54.         return "redirect:/list";  
  55.     }  
  56.        
  57.     @RequestMapping(value = "/Access_Denied", method = RequestMethod.GET)  
  58.     public String accessDeniedPage(ModelMap model) {  
  59.         model.addAttribute("user", getPrincipal());  
  60.         return "accessDenied";  
  61.     }  
  62.    
  63.     @RequestMapping(value = "/login", method = RequestMethod.GET)  
  64.     public String loginPage() {  
  65.         return "login";  
  66.     }  
  67.    
  68.     @RequestMapping(value="/logout", method = RequestMethod.GET)  
  69.     public String logoutPage (HttpServletRequest request, HttpServletResponse response) {  
  70.         Authentication auth = SecurityContextHolder.getContext().getAuthentication();  
  71.         if (auth != null){      
  72.             new SecurityContextLogoutHandler().logout(request, response, auth);  
  73.         }  
  74.         return "redirect:/login?logout";  
  75.     }  
  76.    
  77.     private String getPrincipal(){  
  78.         String userName = null;  
  79.         Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();  
  80.    
  81.         if (principal instanceof UserDetails) {  
  82.             userName = ((UserDetails)principal).getUsername();  
  83.         } else {  
  84.             userName = principal.toString();  
  85.         }  
  86.         return userName;  
  87.     }  
  88.    
  89. }  
package com.websystique.springsecurity.controller;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.security.core.Authentication;

import org.springframework.security.core.context.SecurityContextHolder;

import org.springframework.security.core.userdetails.UserDetails;

import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;

import org.springframework.stereotype.Controller;

import org.springframework.ui.ModelMap;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod; import com.websystique.springsecurity.model.User;

import com.websystique.springsecurity.service.UserService; @Controller

public class HelloWorldController {
@Autowired
UserService service; @RequestMapping(value = { "/", "/list" }, method = RequestMethod.GET)
public String listAllUsers(ModelMap model) { List&lt;User&gt; users = service.findAllUsers();
model.addAttribute("users", users);
return "allusers";
} @RequestMapping(value = { "/edit-user-{id}" }, method = RequestMethod.GET)
public String editUser(@PathVariable int id, ModelMap model) {
User user = service.findById(id);
model.addAttribute("user", user);
model.addAttribute("edit", true);
return "registration";
} @RequestMapping(value = { "/edit-user-{id}" }, method = RequestMethod.POST)
public String updateUser(User user, ModelMap model, @PathVariable int id) {
service.updateUser(user);
model.addAttribute("success", "User " + user.getFirstName() + " updated successfully");
return "success";
} @RequestMapping(value = { "/delete-user-{id}" }, method = RequestMethod.GET)
public String deleteUser(@PathVariable int id) {
service.deleteUser(id);
return "redirect:/list";
} @RequestMapping(value = "/Access_Denied", method = RequestMethod.GET)
public String accessDeniedPage(ModelMap model) {
model.addAttribute("user", getPrincipal());
return "accessDenied";
} @RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginPage() {
return "login";
} @RequestMapping(value="/logout", method = RequestMethod.GET)
public String logoutPage (HttpServletRequest request, HttpServletResponse response) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null){
new SecurityContextLogoutHandler().logout(request, response, auth);
}
return "redirect:/login?logout";
} private String getPrincipal(){
String userName = null;
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); if (principal instanceof UserDetails) {
userName = ((UserDetails)principal).getUsername();
} else {
userName = principal.toString();
}
return userName;
}

}

项目代码将在文章最后提供。

不部署 & 运行

下载本文末尾的项目代码 在一个 Servlet 3.0 容器中发布本应用. 在这里我使用的是tomcat

打开浏览器访问 http://localhost:8080/SpringSecurityMethodLevelSecurityAnnotationExample/, 将被转到登录界面. 填入 USER 权限的证书。

提交表单,能够看到用户列表

尝试删除用户,就会转到 访问拒绝页面因为USER 角色没有删除权限。

用ADMIN角色的账户登录

提交表单将看到用户列表页面

编辑第一行 带有“admin”权限的用户

回到用户列表界面

编辑一个带有dba角色的账户

访问拒绝的原因是带有@PostAuthorize
注解的findById 方法,带有Spring EL表单式限制只有dba角色的用户才可以调用。

只能够删除dba角色的账户,删除其他账户都会出现访问拒绝页面。

退出然后用拥有DBA角色的账户登录 
[dba,root123],点击第一个用户的删除链接。这个用户将被成功删除掉。

项目源码下载地址:http://websystique.com/?smd_process_download=1&download_id=1475

Spring Security 4 使用@PreAuthorize,@PostAuthorize, @Secured, EL实现方法安全的更多相关文章

  1. Security注解:@PreAuthorize,@PostAuthorize, @Secured, EL实现方法安全

     说明 (1)JDK版本:1.8(2)Spring Boot 2.0.6(3)Spring Security 5.0.9(4)Spring Data JPA 2.0.11.RELEASE(5)hibe ...

  2. Spring Security 4 Method security using @PreAuthorize,@PostAuthorize, @Secured, EL--转

    原文地址:http://websystique.com/spring-security/spring-security-4-method-security-using-preauthorize-pos ...

  3. 255.Spring Boot+Spring Security:使用md5加密

    说明 (1)JDK版本:1.8 (2)Spring Boot 2.0.6 (3)Spring Security 5.0.9 (4)Spring Data JPA 2.0.11.RELEASE (5)h ...

  4. 256.Spring Boot+Spring Security: MD5是加密算法吗?

    说明 (1)JDK版本:1.8 (2)Spring Boot 2.0.6 (3)Spring Security 5.0.9 (4)Spring Data JPA 2.0.11.RELEASE (5)h ...

  5. spring security 在controller层 方法级别使用注解 @PreAuthorize("hasRole('ROLE_xxx')")设置权限拦截 ,无权限则返回403

    1.前言 以前学习的时候使用权限的拦截,一般都是对路径进行拦截 ,要么用拦截器设置拦截信息,要么是在配置文件内设置拦截信息, spring security 支持使用注解的形式 ,写在方法和接口上拦截 ...

  6. Spring Security:Authorization 授权(二)

    Authorization 授权 在更简单的应用程序中,身份验证可能就足够了:用户进行身份验证后,便可以访问应用程序的每个部分. 但是大多数应用程序都有权限(或角色)的概念.想象一下:有权访问你的面向 ...

  7. Spring Security(16)——基于表达式的权限控制

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

  8. spring security注解(1)

    Chapter 15. 基于表达式的权限控制 Spring Security 3.0介绍了使用Spring EL表达式的能力,作为一种验证机制 添加简单的配置属性的使用和访问决策投票,就像以前一样. ...

  9. Spring Security方法级别授权使用介绍

    1.简介 简而言之,Spring Security支持方法级别的授权语义. 通常,我们可以通过限制哪些角色能够执行特定方法来保护我们的服务层 - 并使用专用的方法级安全测试支持对其进行测试. 在本文中 ...

随机推荐

  1. MySQL事务、锁机制、查询缓存

    MySQL事务 何为事务? 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit). 一个事务可以是一条SQL语句,一组SQL语句或整个程序. 事务的特性: 事 ...

  2. python \r \t \n 各种转义字符

    转义字符 描述 \(在行尾时) 续行符 \\ 反斜杠符号 \’ 单引号 \” 双引号 \a 响铃 \b 退格(Backspace) \e 转义 \000 空 \n 换行 \v 纵向制表符 \t 横向制 ...

  3. falsh 遮住div 解决方案

    1.修改代码 <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http ...

  4. AT2164 Rabbit Exercise

    传送门 解题思路 首先考虑k=1的情况,对于每一个a[i],它可能会到a[i-1]*2-a[i] 与 a[i+1]*2-a[i]两个位置,概率都为%50,那么它的期望位置为 (a[i-1]*2-a[i ...

  5. jquery全部选是,全部选否。

    <div class="col-md-9"> <div class="box box-primary"> <div class=& ...

  6. echarts--例子

    echarts使用例子: <script type="text/javascript"> option = { title : {'x': 'center','y':' ...

  7. angular依赖注入(1)——从父元素到子元素的数据注入

    1.什么是依赖注入? 依赖注入是一种编程模式,可以让类从外部源中获得它的依赖,不必亲自创建他们. (这就达到了一个效果,我不知道我是怎么实现的,但我创建了一个实现他的接口,然后接口封装起来,1.可以分 ...

  8. 小希的迷宫 HDU - 1272 (并查集)

    思路: 当图中的集合(连通子图)个数为1并且边数等于顶点数-1(即改图恰好为一棵生成树)时,输出Yes. 此题的坑:(1) 如果只输入0 0算作一组数据的话答案应该输出Yes (2) 输入数据可能并不 ...

  9. @at-root和#{&}结合

    Sass有脚本模式#{},他和&不同之处是,&只用作选择器,它只能出现在一个复合的开始选择器,类似于一个类型选择器,如a或者h1.但#{}他表示的是一个插值,它可以用在任何地方.同样的 ...

  10. LINUX配置文件介绍

    每个 Linux 程序都是一个可执行文件,它含有操作码列表,CPU 将执行这些操作码来完成特定的操作.例如,ls 命令是由 /bin/ls 文件提供的,该文件含有机器指令的列表,在屏幕上显示当前目录中 ...