spring security method security

参考

Spring Security 官方文档

http://www.concretepage.com/spring/spring-security/preauthorize-postauthorize-in-spring-security

方法调用安全

对应的注解@EnableGlobalMethodSecurity,该注解放在GlobalMethodSecurityConfiguration的子类上方

@EnableGlobalMethodSecurity(prePostEnabled = true)

使用的Voter

org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter

有俩对对应的注解

@PreAuthorize 决定方法是否可以被调用

@PostAuthorize 决定方法是否可以返回该值

@PreFilter

@PostFilter

如下:

package com.jiangchong.methodsecurity;

import org.springframework.security.access.method.P;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;

public interface IBookService
{
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public void addBook(Book book);

    // PostAuthorize,决定这个值是否可以被返回,使用returnObject
    /*
     * Less commonly, you may wish to perform an access-control check after the
     * method has been invoked. This can be achieved using the @PostAuthorize
     * annotation. To access the return value from a method, use the built-in
     * name returnObject in the expression.
     */
    @PostAuthorize("returnObject.owner == authentication.name")
    public Book getBook();

    // PreAuthorize,决定这个方法是否可以被调用
    /*
     * @P单个参数的方法
     */
    @PreAuthorize("#b.owner == authentication.name")
    public void deleteBook(@P("b") Book book);
    /*
     * @Param放在至少有一个参数的方法的上
     * 
     * @PreAuthorize("#n == authentication.name") Contact
     * findContactByName(@Param("n") String name)
     */
    // springEL
    /*
     * @PreAuthorize("#contact.name == authentication.name") public void
     * doSomething(Contact contact);
     */

}

测试的Demo,基于Spring Boot

Pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jiangchong</groupId>
    <artifactId>methodsecurity</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>methodsecurity</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.2.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
        </dependency>
    </dependencies>
</project>

App.class

package com.jiangchong.methodsecurity;

import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 *
 */
@RestController
@SpringBootApplication
public class App
{
    @Autowired
    public IBookService bookService;

    public static void main(String[] args)
    {
        SpringApplication.run(App.class, args);
    }

    @RequestMapping("/")
    public Map<String, String> test()
    {
        Book b1 = new Book("A", "admin");
        bookService.addBook(b1);
        bookService.getBook();
        System.out.println("user return");
        Book b2 = new Book("B", "user");
        bookService.deleteBook(b2);
        return null;
    }
    /*
     * @RequestMapping("/admin") public Map<String, String> testAdmin() {
     * Map<String, String> map = new HashMap<>(); map.put("admin", "admin");
     * return map; }
     * 
     * @RequestMapping("/user") public Map<String, String> testUser(String name)
     * { Map<String, String> map = new HashMap<>(); map.put("user", "user");
     * return map; }
     * 
     * @RequestMapping("/resource/test") public Map<String, String>
     * testResouce() { Map<String, String> map = new HashMap<>();
     * map.put("test", "resource"); return map; }
     */
}

Book.class

package com.jiangchong.methodsecurity;

public class Book
{
    private String name;
    private String owner;

    public Book(String name, String owner)
    {
        this.name = name;
        this.owner = owner;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public String getOwner()
    {
        return owner;
    }

    public void setOwner(String owner)
    {
        this.owner = owner;
    }
}

BookService.class

package com.jiangchong.methodsecurity;

import org.springframework.stereotype.Service;

@Service
public class BookService implements IBookService
{
    @Override
    public void addBook(Book book)
    {
        System.out.println("You have successfully added book.");
    }

    @Override
    public Book getBook()
    {
        Book book = new Book("B", "user");
        System.out.println("return " + book.getOwner());
        return book;
    }

    @Override
    public void deleteBook(Book book)
    {
        System.out.println("Books deleted");
    }

}

IBookService

package com.jiangchong.methodsecurity;

import org.springframework.security.access.method.P;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;

public interface IBookService
{
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public void addBook(Book book);

    // PostAuthorize,决定这个值是否可以被返回,使用returnObject
    /*
     * Less commonly, you may wish to perform an access-control check after the
     * method has been invoked. This can be achieved using the @PostAuthorize
     * annotation. To access the return value from a method, use the built-in
     * name returnObject in the expression.
     */
    @PostAuthorize("returnObject.owner == authentication.name")
    public Book getBook();

    // PreAuthorize,决定这个方法是否可以被调用
    /*
     * @P单个参数的方法
     */
    @PreAuthorize("#b.owner == authentication.name")
    public void deleteBook(@P("b") Book book);
    /*
     * @Param放在至少有一个参数的方法的上
     * 
     * @PreAuthorize("#n == authentication.name") Contact
     * findContactByName(@Param("n") String name)
     */
    // springEL
    /*
     * @PreAuthorize("#contact.name == authentication.name") public void
     * doSomething(Contact contact);
     */

}

MethodSecurityConfig

package com.jiangchong.methodsecurity;

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.method.configuration.GlobalMethodSecurityConfiguration;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration
{
    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception
    {
        auth.inMemoryAuthentication();
    }

}

WebSecurityConfig

package com.jiangchong.methodsecurity;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
    protected void configure(HttpSecurity http) throws Exception
    {
        http.authorizeRequests().anyRequest().authenticated().and().formLogin()
                .loginProcessingUrl("/login").permitAll();
    }

    public void configure(WebSecurity web) throws Exception
    {
        web.ignoring().antMatchers("/resource/**");
    }

    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception
    {
        auth.inMemoryAuthentication().withUser("admin").password("admin")
                .roles("ADMIN").and().withUser("user").password("user")
                .roles("USER");
    }

}
    Book b1 = new Book("A", "admin");
    bookService.addBook(b1);
    bookService.getBook();
    System.out.println("user return");
    Book b2 = new Book("B", "user");
    bookService.deleteBook(b2);
这些调用序列,只要有一个不满足权限,后面的方法不会再调用
原文地址:https://www.cnblogs.com/shuiyonglewodezzzzz/p/5206000.html