Grundlegende und systematische Geschichte Zertifizierungs- / Autorisierungsgeschichte Remember-Me-Geschichte CSRF-Geschichte Session Management Story Geschichte des Antwortheaders Method Security Story CORS-Geschichte Die Geschichte von Run-As Teststory Sprechen Sie über die Zusammenarbeit mit MVC und Boot
Sonderedition Was Spring Security kann und was nicht
Die Autorisierungsverarbeitung mit hasAuthority () usw. wird grundsätzlich in Funktionseinheiten gesteuert. (Eine bestimmte Funktion (Bildschirm) muss die Berechtigung XX usw. haben.)
Beim tatsächlichen Erstellen eines Systems ist es jedoch selten erforderlich, Berechtigungen datenweise zu verwalten. Beispielsweise können nur Personen, die derselben Gruppe angehören wie die Person, die die Daten erstellt hat, die Daten sehen, oder nur der Ersteller oder Systemadministrator kann die Daten aktualisieren.
Spring Security bietet einen Mechanismus, um eine solche Zugriffskontrolle datenweise zu realisieren.
Dies wird als Domänenobjektsicherheit oder ACL (Access Control List) bezeichnet.
Hello World
build.gradle
dependencies {
compile 'org.springframework.security:spring-security-web:4.2.1.RELEASE'
compile 'org.springframework.security:spring-security-config:4.2.1.RELEASE'
compile 'org.springframework.security:spring-security-acl:4.2.1.RELEASE'★ Ergänzung
compile 'org.springframework:spring-jdbc:4.3.7.RELEASE'
compile 'com.h2database:h2:1.4.193'
}
DB
src/main/resources/sql/create_acl_tables.sql
CREATE TABLE ACL_SID (
ID BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
PRINCIPAL BOOLEAN NOT NULL,
SID VARCHAR_IGNORECASE(100) NOT NULL,
CONSTRAINT UNIQUE_UK_1 UNIQUE(SID,PRINCIPAL)
);
CREATE TABLE ACL_CLASS(
ID BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
CLASS VARCHAR_IGNORECASE(100) NOT NULL,
CONSTRAINT UNIQUE_UK_2 UNIQUE(CLASS)
);
CREATE TABLE ACL_OBJECT_IDENTITY(
ID BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
OBJECT_ID_CLASS BIGINT NOT NULL,
OBJECT_ID_IDENTITY BIGINT NOT NULL,
PARENT_OBJECT BIGINT,
OWNER_SID BIGINT,
ENTRIES_INHERITING BOOLEAN NOT NULL,
CONSTRAINT UNIQUE_UK_3 UNIQUE(OBJECT_ID_CLASS, OBJECT_ID_IDENTITY),
CONSTRAINT FOREIGN_FK_1 FOREIGN KEY(PARENT_OBJECT)REFERENCES ACL_OBJECT_IDENTITY(ID),
CONSTRAINT FOREIGN_FK_2 FOREIGN KEY(OBJECT_ID_CLASS)REFERENCES ACL_CLASS(ID),
CONSTRAINT FOREIGN_FK_3 FOREIGN KEY(OWNER_SID)REFERENCES ACL_SID(ID)
);
CREATE TABLE ACL_ENTRY(
ID BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
ACL_OBJECT_IDENTITY BIGINT NOT NULL,
ACE_ORDER INT NOT NULL,
SID BIGINT NOT NULL,
MASK INTEGER NOT NULL,
GRANTING BOOLEAN NOT NULL,
AUDIT_SUCCESS BOOLEAN NOT NULL,
AUDIT_FAILURE BOOLEAN NOT NULL,
CONSTRAINT UNIQUE_UK_4 UNIQUE(ACL_OBJECT_IDENTITY, ACE_ORDER),
CONSTRAINT FOREIGN_FK_4 FOREIGN KEY(ACL_OBJECT_IDENTITY) REFERENCES ACL_OBJECT_IDENTITY(ID),
CONSTRAINT FOREIGN_FK_5 FOREIGN KEY(SID) REFERENCES ACL_SID(ID)
);
src/main/resources/sql/insert_acl_tables.sql
INSERT INTO ACL_CLASS (ID, CLASS)
VALUES (100, 'sample.spring.security.domain.Foo');
INSERT INTO ACL_SID (ID, PRINCIPAL, SID)
VALUES (9, true, 'hoge');
INSERT INTO ACL_SID (ID, PRINCIPAL, SID)
VALUES (99, false, 'SAMPLE_AUTHORITY');
INSERT INTO ACL_OBJECT_IDENTITY (ID, OBJECT_ID_CLASS, OBJECT_ID_IDENTITY, PARENT_OBJECT, OWNER_SID, ENTRIES_INHERITING)
VALUES (1000, 100, 44, NULL, 9, true);
INSERT INTO ACL_ENTRY (ID, ACL_OBJECT_IDENTITY, ACE_ORDER, SID, MASK, GRANTING, AUDIT_SUCCESS, AUDIT_FAILURE)
VALUES (10, 1000, 0, 99, 1, true, false, false);
Foo.java
package sample.spring.security.domain;
public class Foo {
private final long id;
public Foo(long id) {
this.id = id;
}
public long getId() {
return id;
}
@Override
public String toString() {
return "Foo{id=" + id + '}';
}
}
MyAclSampleService.java
package sample.spring.security.service;
import org.springframework.security.access.prepost.PreAuthorize;
import sample.spring.security.domain.Foo;
public class MyAclSampleService {
@PreAuthorize("hasPermission(#foo, read)")
public void logic(Foo foo) {
System.out.println("foo=" + foo);
}
}
--Standardausgabe von "foo" als Argument erhalten
MyAclServlet.java
package sample.spring.security.servlet;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import sample.spring.security.domain.Foo;
import sample.spring.security.service.MyAclSampleService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.stream.Collectors;
@WebServlet("/acl")
public class MyAclServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.printPrincipal();
this.callServiceLogic(new Foo(44L), req);
this.callServiceLogic(new Foo(45L), req);
}
private void printPrincipal() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String name = auth.getName();
System.out.println("name=" + name);
System.out.println("authorities=" +
auth.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.joining(", "))
);
}
private void callServiceLogic(Foo foo, HttpServletRequest req) {
try {
this.findServiceBean(req).logic(foo);
} catch (AccessDeniedException e) {
System.out.println("AccessDeniedException : " + e.getMessage());
}
}
private MyAclSampleService findServiceBean(HttpServletRequest req) {
WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(req.getServletContext());
return context.getBean(MyAclSampleService.class);
}
}
--Nach der Ausgabe der Informationen des aktuellen Principals erstellen Sie eine Instanz von Foo
mit id = 44
und id = 45
und führen dielogic ()
Methode von MyAclSampleService
aus.
namespace
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
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.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="classpath:/sql/create_acl_tables.sql" />
<jdbc:script location="classpath:/sql/insert_acl_tables.sql" />
</jdbc:embedded-database>
<sec:global-method-security pre-post-annotations="enabled">
<sec:expression-handler ref="expressionHandler" />
</sec:global-method-security>
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator">
<bean class="org.springframework.security.acls.AclPermissionEvaluator">
<constructor-arg ref="aclService" />
</bean>
</property>
</bean>
<bean id="aclService" class="org.springframework.security.acls.jdbc.JdbcAclService">
<constructor-arg ref="dataSource" />
<constructor-arg ref="lookupStrategy" />
</bean>
<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
<constructor-arg ref="dataSource" />
<constructor-arg ref="aclCache" />
<constructor-arg ref="aclAuthorizationStrategy" />
<constructor-arg ref="permissionGrantingStrategy" />
</bean>
<bean id="aclCache" class="org.springframework.security.acls.domain.SpringCacheBasedAclCache">
<constructor-arg>
<bean class="org.springframework.cache.support.NoOpCache">
<constructor-arg value="myCache" />
</bean>
</constructor-arg>
<constructor-arg ref="permissionGrantingStrategy" />
<constructor-arg ref="aclAuthorizationStrategy" />
</bean>
<bean id="aclAuthorizationStrategy" class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
<constructor-arg>
<list>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="TEST"/>
</bean>
</list>
</constructor-arg>
</bean>
<bean id="permissionGrantingStrategy" class="org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy">
<constructor-arg>
<bean class="org.springframework.security.acls.domain.ConsoleAuditLogger" />
</constructor-arg>
</bean>
<bean class="sample.spring.security.service.MyAclSampleService" />
<sec:http>
<sec:intercept-url pattern="/login" access="permitAll" />
<sec:intercept-url pattern="/**" access="isAuthenticated()" />
<sec:form-login />
<sec:logout />
</sec:http>
<sec:authentication-manager>
<sec:authentication-provider>
<sec:user-service>
<sec:user name="foo" password="foo" authorities="" />
<sec:user name="bar" password="bar" authorities="SAMPLE_AUTHORITY" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
</beans
Java Configuration
MySpringSecurityConfig.java
package sample.spring.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import sample.spring.security.service.MyAclSampleService;
import java.util.Collections;
@EnableWebSecurity
@Import(MyGlobalMethodSecurityConfig.class)
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin();
}
@Bean
public MyAclSampleService myAclSampleService() {
return new MyAclSampleService();
}
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("foo")
.password("foo")
.authorities(Collections.emptyList())
.and()
.withUser("bar")
.password("bar")
.authorities("SAMPLE_AUTHORITY");
}
}
MyGlobalMethodSecurityConfig.java
package sample.spring.security;
import org.springframework.cache.support.NoOpCache;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.acls.AclPermissionEvaluator;
import org.springframework.security.acls.domain.AclAuthorizationStrategy;
import org.springframework.security.acls.domain.AclAuthorizationStrategyImpl;
import org.springframework.security.acls.domain.ConsoleAuditLogger;
import org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy;
import org.springframework.security.acls.domain.SpringCacheBasedAclCache;
import org.springframework.security.acls.jdbc.BasicLookupStrategy;
import org.springframework.security.acls.jdbc.JdbcAclService;
import org.springframework.security.acls.jdbc.LookupStrategy;
import org.springframework.security.acls.model.AclCache;
import org.springframework.security.acls.model.AclService;
import org.springframework.security.acls.model.PermissionGrantingStrategy;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import javax.sql.DataSource;
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class MyGlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(EmbeddedDatabaseType.H2)
.setScriptEncoding("UTF-8")
.addScripts("/sql/create_acl_tables.sql", "/sql/insert_acl_tables.sql")
.build();
}
@Bean
public PermissionEvaluator permissionEvaluator(AclService aclService) {
return new AclPermissionEvaluator(aclService);
}
@Bean
public AclService aclService(DataSource dataSource, LookupStrategy lookupStrategy) {
return new JdbcAclService(dataSource, lookupStrategy);
}
@Bean
public LookupStrategy lookupStrategy(DataSource dataSource, AclCache aclCache, AclAuthorizationStrategy aclAuthorizationStrategy, PermissionGrantingStrategy permissionGrantingStrategy) {
return new BasicLookupStrategy(
dataSource,
aclCache,
aclAuthorizationStrategy,
permissionGrantingStrategy
);
}
@Bean
public AclCache aclCache(PermissionGrantingStrategy permissionGrantingStrategy, AclAuthorizationStrategy aclAuthorizationStrategy) {
return new SpringCacheBasedAclCache(
new NoOpCache("myCache"),
permissionGrantingStrategy,
aclAuthorizationStrategy
);
}
@Bean
public AclAuthorizationStrategy aclAuthorizationStrategy() {
return new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("TEST"));
}
@Bean
public PermissionGrantingStrategy permissionGrantingStrategy() {
return new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger());
}
}
Melden Sie sich als foo
Benutzer an und greifen Sie / acl
zu.
Ausgabe der Serverkonsole
name=foo
authorities=
AccessDeniedException : Access is denied
AccessDeniedException : Access is denied
Sowohl "id = 44" als auch "id = 45" wurde der Zugriff verweigert.
Melden Sie sich dann als "bar" -Benutzer an und greifen Sie auf "/ acl" zu.
Ausgabe der Serverkonsole
name=bar
authorities=SAMPLE_AUTHORITY
foo=Foo{id=44}
AccessDeniedException : Access is denied
id = 44
hat dielogic ()
Methode erfolgreich ausgeführt, und id = 45
hat den Zugriff verweigert.
Die folgenden vier werden angezeigt.
ACL_SID
ACL_CLASS
ACL_OBJECT_IDENTITY
ACL_ENTRY
Die Tabellenstruktur sieht wie folgt aus.
Der Pfeil steht für FK, die Quelle des Pfeils ist die Referrer-Tabelle und die Spitze des Pfeils ist die Referrer-Tabelle.
Die Bedeutung jeder Tabelle und Spalte ist wie folgt.
ACL_CLASS
Säule | Bedeutung |
---|---|
CLASS |
Java-Klassenname (FQCN) des Domänenobjekts |
ACL_SID
GrantedAuthority
) oder einen Auftraggeber
--SID steht für Security Identity
Säule | Bedeutung |
---|---|
PRINCIPAL |
Ein Flag, das unterscheidet, ob dieser Datensatz ein Principal isttrue → Auftraggeberfalse → GrantedAuthority |
SID |
Eine Zeichenfolge, die die SID darstellt. Wenn Sie ein Schulleiter sind username 、 GrantedAuthority Dann wird der Zeichenfolgenausdruck gesetzt |
ACL_OBJECT_IDENTITY
Säule | Bedeutung |
---|---|
OBJECT_ID_CLASS |
Eine Spalte, die auf eine Klasse von Domänenobjekten verweist.ACL_CLASS Extern verwiesen auf. |
OBJECT_ID_IDENTITY |
ID, die die Instanz identifiziert |
PARENT_OBJECT |
ElternACL_OBJECT_IDENTITY ICH WÜRDE |
OWNER_SID |
Erstellt diese InstanzACL_SID ICH WÜRDE |
ENTRIES_INHERITING |
Flags, ob diese Instanz Berechtigungsvererbungsbeziehungen zu anderen Instanzen hat |
ACL_ENTRY
Säule | Bedeutung |
---|---|
ACL_OBJECT_IDENTITY |
Wenden Sie diese Berechtigungsdefinition anACL_OBJECT_IDENTITY ICH WÜRDE |
ACE_ORDER |
EinerACL_OBJECT_IDENTITY Zu mehrfachACL_ENTRTY Bestellen, wann verknüpft ist |
SID |
Wenden Sie diese Berechtigungsdefinition anACL_SID ICH WÜRDE |
MASK |
Ganzzahliger Wert, der die Berechtigungsdefinition darstellt (Details werden später beschrieben) |
GRANTING |
Flag "Grant" oder "Reject" |
AUDIT_SUCCESS |
Flag zur Ausgabe des Überwachungsprotokolls, wenn diese Berechtigungsdefinition erteilt wird |
AUDIT_FAILUER |
Flag zur Ausgabe des Überwachungsprotokolls, wenn diese Berechtigungsdefinition verweigert wird |
Die in Hello World verwendeten Daten hatten eine Struktur wie ↓.
MASK
ist die Definition von BerechtigungenSID
ist auf ACL_SID
gesetzt, auf die die Berechtigung angewendet wird.ACL_ENTRY
bedeuten" Wenn Sie die Berechtigung ** SAMPLE_AUTHORITY
haben, können Sie das Foo
-Objekt mit id = 44
** lesen".We do not intend to support non-long identifiers in Spring Security’s ACL module, as longs are already compatible with all database sequences, the most common identifier data type, and are of sufficient length to accommodate all common usage scenarios.
(Übersetzung) Wir beabsichtigen nicht, ** nicht lange Bezeichner im Spring Security ACL-Modul zu unterstützen **.
long
ist bereits mit allen Datenbanksequenzen kompatibel, ist der häufigste Datentyp und lang genug, um alle gängigen Verwendungsszenarien zu speichern.
applicationContext.xml
<sec:global-method-security pre-post-annotations="enabled">
<sec:expression-handler ref="expressionHandler" />
</sec:global-method-security>
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator">
<bean class="org.springframework.security.acls.AclPermissionEvaluator">
<constructor-arg ref="aclService" />
</bean>
</property>
</bean>
AclPermissionEvaluator
ist dafür eingestellt.applicationContext.xml
<bean id="aclService" class="org.springframework.security.acls.jdbc.JdbcAclService">
<constructor-arg ref="dataSource" />
<constructor-arg ref="lookupStrategy" />
</bean>
--AclService
bietet ACL-Funktionalität
--JdbcAclService
verwendet JDBC, um auf in der Datenbank definierte Informationen zuzugreifen und ACL-Funktionen zu implementieren.
LookupStrategy
applicationContext.xml
<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
<constructor-arg ref="dataSource" />
<constructor-arg ref="aclCache" />
<constructor-arg ref="aclAuthorizationStrategy" />
<constructor-arg ref="permissionGrantingStrategy" />
</bean>
BasicLookupStrategy
ist eine Implementierung, die JDBC zum Abrufen von ACL-Definitionsinformationen verwendet.applicationContext.xml
<bean id="aclCache" class="org.springframework.security.acls.domain.SpringCacheBasedAclCache">
<constructor-arg>
<bean class="org.springframework.cache.support.NoOpCache">
<constructor-arg value="myCache" />
</bean>
</constructor-arg>
<constructor-arg ref="permissionGrantingStrategy" />
<constructor-arg ref="aclAuthorizationStrategy" />
</bean>
NoOpCache
für die eigentliche Cache-Implementierung--SpringCacheBasedAclCache
speichert Objekte der Klasse AclImpl
zwischen
AclImpl
ansieht, sieht es so aus:AclImpl.java
private Acl parentAcl;
private transient AclAuthorizationStrategy aclAuthorizationStrategy;
private transient PermissionGrantingStrategy permissionGrantingStrategy;
private final List<AccessControlEntry> aces = new ArrayList<AccessControlEntry>();
private ObjectIdentity objectIdentity;
private Serializable id;
private Sid owner; // OwnershipAcl
private List<Sid> loadedSids = null; // includes all SIDs the WHERE clause covered,
--AclImpl
implementiert die Acl
-Schnittstelle und Acl
erbt Serializable
.
AclImpl
serialisierbar sein und alle oben genannten Felder sind grundsätzlich serialisierbar.Übrigens muss "BasicLookupStrategy" auch Instanzen von "AclAuthorizationStrategy" und "PermissionGrantingStrategy" als Konstruktorargumente empfangen.
applicationContext.xml
<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
...
<constructor-arg ref="aclAuthorizationStrategy" />
<constructor-arg ref="permissionGrantingStrategy" />
</bean>
Dies wird verwendet, um festzulegen, wann BasicLookupStrategy
das AclImpl
-Objekt aus den Datenbankinformationen rekonstruiert.
AclAuthorizationStrategy
applicationContext.xml
<bean id="aclAuthorizationStrategy" class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
<constructor-arg>
<list>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="TEST"/>
</bean>
</list>
</constructor-arg>
</bean>
--AclAuthorizationStrategy
ist dafür verantwortlich, zu überprüfen, ob der aktuelle Principal diese Berechtigung hat, wenn er die ACL-Definition ändert.
―― Mit anderen Worten, es wird in dieser Hello World nicht wirklich verwendet
PermissionGrantingStrategy
applicationContext.xml
<bean id="permissionGrantingStrategy" class="org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy">
<constructor-arg>
<bean class="org.springframework.security.acls.domain.ConsoleAuditLogger" />
</constructor-arg>
</bean>
--PermissionGrantingStrategy
bietet einen Prozess, mit dem speziell ermittelt werden kann, ob der aktuelle Principal über die durchhasPermission ()
angegebenen Berechtigungen verfügt.
AuditLogger
--AuditLogger
bietet einen Prozess zum Protokollieren des Ergebnisses der Berechtigungsbeurteilung.
--ConsoleAuditLogger
ist die einzige bereitgestellte Implementierungsklasse und gibt das Ergebnis an die Konsole aus.
So was.
hasPermission()
MyAclSampleService.java
@PreAuthorize("hasPermission(#foo, read)")
public void logic(Foo foo) {
hasPermission ()
, um die ACL zu bestimmenMyAclSampleService.java
@PreAuthorize("hasPermission(#id, 'sample.spring.security.domain.Foo', read)")
public void logic(long id) {
SecurityExpressionRoot.java
public final String read = "read";
public final String write = "write";
public final String create = "create";
public final String delete = "delete";
public final String admin = "administration";
Definitionen von Berechtigungen ("Lesen", "Schreiben", "Erstellen", "Löschen", "Verwaltung") werden als ganzzahlige Werte ausgedrückt. In der Datenbank wird es in der Spalte "MASK" von "ACL_ENTRY" gespeichert.
Jede Berechtigung ist wie unten gezeigt jedem Binärbit zugeordnet.
5. Bit | 4. Bit | 3. Bit | 2. Bit | 1. Bit |
---|---|---|---|---|
administration | delete | create | write | read |
Mit anderen Worten
Genehmigung | Binäre Darstellung | Dezimaldarstellung |
---|---|---|
read |
00001 |
1 |
write |
00010 |
2 |
create |
00100 |
4 |
delete |
01000 |
8 |
administration |
10000 |
16 |
Sie fragen sich vielleicht: "Wenn Sie dann zwei Berechtigungen haben möchten," Lesen "und" Schreiben ", ist es" 00011 "(" 3 "in Dezimalzahl)?", Aber das ist nicht der Fall.
Bis zum letzten wird eine der oben genannten fünf in MASK
jedes ACL_ENTRY
-Datensatzes eingegeben.
Wenn Sie mehrere Berechtigungen erteilen, wird die Anzahl der Datensätze registriert.
(Ist das eine Maske?)
Eingabedaten
INSERT INTO ACL_CLASS (ID, CLASS)
VALUES (100, 'sample.spring.security.domain.Foo');
INSERT INTO ACL_SID (ID, PRINCIPAL, SID)
VALUES (9, true, 'hoge');
INSERT INTO ACL_SID (ID, PRINCIPAL, SID)
VALUES (98, false, 'AUTHORITY_10101');
INSERT INTO ACL_SID (ID, PRINCIPAL, SID)
VALUES (99, false, 'AUTHORITY_01010');
INSERT INTO ACL_OBJECT_IDENTITY (ID, OBJECT_ID_CLASS, OBJECT_ID_IDENTITY, PARENT_OBJECT, OWNER_SID, ENTRIES_INHERITING)
VALUES (1000, 100, 44, NULL, 9, true);
-- AUTHORITY_10101
INSERT INTO ACL_ENTRY (ID, ACL_OBJECT_IDENTITY, ACE_ORDER, SID, MASK, GRANTING, AUDIT_SUCCESS, AUDIT_FAILURE)
VALUES (10, 1000, 0, 98, 1, true, false, false); -- read(00001 = 1)
INSERT INTO ACL_ENTRY (ID, ACL_OBJECT_IDENTITY, ACE_ORDER, SID, MASK, GRANTING, AUDIT_SUCCESS, AUDIT_FAILURE)
VALUES (11, 1000, 1, 98, 4, true, false, false); -- create(00100 = 4)
INSERT INTO ACL_ENTRY (ID, ACL_OBJECT_IDENTITY, ACE_ORDER, SID, MASK, GRANTING, AUDIT_SUCCESS, AUDIT_FAILURE)
VALUES (12, 1000, 2, 98, 16, true, false, false); -- administration(10000 = 16)
-- AUTHORITY_01010
INSERT INTO ACL_ENTRY (ID, ACL_OBJECT_IDENTITY, ACE_ORDER, SID, MASK, GRANTING, AUDIT_SUCCESS, AUDIT_FAILURE)
VALUES (13, 1000, 3, 99, 10, true, false, false); -- write, delete(01010 = 10)
--Grant read (1)
, create (4)
undadministrative (16)
Berechtigungen für AUTHORITY_10101
einzeln.
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
...>
...
<sec:authentication-manager>
<sec:authentication-provider>
<sec:user-service>
<sec:user name="foo" password="foo" authorities="AUTHORITY_10101" />
<sec:user name="bar" password="bar" authorities="AUTHORITY_01010" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
</beans>
AUTHORITY_01010
an den bar
BenutzerMyAclSampleService.java
package sample.spring.security.service;
import org.springframework.security.access.prepost.PreAuthorize;
import sample.spring.security.domain.Foo;
public class MyAclSampleService {
@PreAuthorize("hasPermission(#foo, read)")
public void read(Foo foo) {
System.out.println("[read] foo=" + foo);
}
@PreAuthorize("hasPermission(#foo, write)")
public void write(Foo foo) {
System.out.println("[write] foo=" + foo);
}
@PreAuthorize("hasPermission(#foo, create)")
public void create(Foo foo) {
System.out.println("[create] foo=" + foo);
}
@PreAuthorize("hasPermission(#foo, delete)")
public void delete(Foo foo) {
System.out.println("[delete] foo=" + foo);
}
@PreAuthorize("hasPermission(#foo, admin)")
public void admin(Foo foo) {
System.out.println("[admin] foo=" + foo);
}
}
MyAclServlet.java
package sample.spring.security.servlet;
...
@WebServlet("/acl")
public class MyAclServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.printPrincipal();
MyAclSampleService serviceBean = this.findServiceBean(req);
Foo foo = new Foo(44L);
this.callServiceLogic("read", () -> serviceBean.read(foo));
this.callServiceLogic("write", () -> serviceBean.write(foo));
this.callServiceLogic("create", () -> serviceBean.create(foo));
this.callServiceLogic("delete", () -> serviceBean.delete(foo));
this.callServiceLogic("admin", () -> serviceBean.admin(foo));
}
private void printPrincipal() {
...
}
private void callServiceLogic(String methodName, Runnable runnable) {
try {
System.out.println("* invoke " + methodName + "()");
runnable.run();
} catch (AccessDeniedException e) {
System.out.println("AccessDeniedException : " + e.getMessage());
}
}
private MyAclSampleService findServiceBean(HttpServletRequest req) {
...
}
}
** Funktionsprüfung **
Serverausgabe beim Anmelden mit foo
name=foo
authorities=AUTHORITY_10101
* invoke read()
[read] foo=Foo{id=44}
* invoke write()
AccessDeniedException : Access is denied
* invoke create()
[create] foo=Foo{id=44}
* invoke delete()
AccessDeniedException : Access is denied
* invoke admin()
[admin] foo=Foo{id=44}
Serverausgabe beim Anmelden mit Leiste
name=bar
authorities=AUTHORITY_01010
* invoke read()
AccessDeniedException : Access is denied
* invoke write()
AccessDeniedException : Access is denied
* invoke create()
AccessDeniedException : Access is denied
* invoke delete()
AccessDeniedException : Access is denied
* invoke admin()
AccessDeniedException : Access is denied
--write
und delete
wurden ebenfalls blockiert
Der Grund wurde in Dieses Problem auf GitHub beschrieben.
Ich bin skeptisch, dass es mir passt, weil meine Englischkenntnisse gering sind, aber ich fühle mich wie folgt.
Obwohl dort "MASKE" steht, fühlt es sich tatsächlich wie eine Division von ganzzahligen Werten an.
Immerhin: "Ich habe einen Erweiterungspunkt vorbereitet. Wenn Sie also wirklich mit einer Bitmaske urteilen möchten, verwenden Sie diesen." SEC-1166: Provide strategy interface for AclImpl isGranted() method.
Bis zu diesem Zeitpunkt wurden Daten wie "ACL_ENTRY" registriert, indem zuvor eine INSERT-Anweisung in SQL vorbereitet wurde.
Es ist jedoch schwierig, diese Tabellen direkt in der tatsächlichen Entwicklung zu bearbeiten, da Sie die Spezifikationen richtig verstehen müssen.
Daher gibt es eine API zum Verwalten dieser Daten.
MyAclSampleService.java
package sample.spring.security.service;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.MutableAclService;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.transaction.annotation.Transactional;
import sample.spring.security.domain.Foo;
@Transactional
public class MyAclSampleService {
private MutableAclService aclService;
public MyAclSampleService(MutableAclService aclService) {
this.aclService = aclService;
}
public void createObjectIdentity() {
ObjectIdentity objectIdentity = new ObjectIdentityImpl(Foo.class, 10L);
MutableAcl acl = this.aclService.createAcl(objectIdentity);
System.out.println("acl = " + acl);
}
}
MyAclServlet.java
package sample.spring.security.servlet;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import sample.spring.security.service.MyAclSampleService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@WebServlet("/acl")
public class MyAclServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
MyAclSampleService service = this.findServiceBean(req, MyAclSampleService.class);
service.createObjectIdentity();
this.printTables(req);
}
private void printTables(HttpServletRequest req) {
this.printTable(req, "ACL_SID");
this.printTable(req, "ACL_CLASS");
this.printTable(req, "ACL_OBJECT_IDENTITY");
this.printTable(req, "ACL_ENTRY");
}
private void printTable(HttpServletRequest req, String table) {
JdbcTemplate jdbcTemplate = this.findServiceBean(req, JdbcTemplate.class);
List<Map<String, Object>> records = jdbcTemplate.queryForList("select * from " + table + " order by id asc");
System.out.println("\n[" + table + "]");
records.forEach(System.out::println);
}
private <T> T findServiceBean(HttpServletRequest req, Class<T> clazz) {
WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(req.getServletContext());
return context.getBean(clazz);
}
}
namespace
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx"
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.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<tx:annotation-driven />
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="classpath:/sql/create_acl_tables.sql" />
</jdbc:embedded-database>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
</bean>
...
<bean id="aclService" class="org.springframework.security.acls.jdbc.JdbcMutableAclService">
<constructor-arg ref="dataSource" />
<constructor-arg ref="lookupStrategy" />
<constructor-arg ref="aclCache" />
</bean>
...
<bean class="sample.spring.security.service.MyAclSampleService">
<constructor-arg ref="aclService" />
</bean>
<bean class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
...
</beans>
Java Configuration
MySpringSecurityConfig.java
package sample.spring.security;
...
import org.springframework.security.acls.model.MutableAclService;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import sample.spring.security.service.MyAclSampleService;
...
@EnableWebSecurity
@EnableTransactionManagement
@Import(MyGlobalMethodSecurityConfig.class)
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
...
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public MyAclSampleService myAclSampleService(MutableAclService aclService) {
return new MyAclSampleService(aclService);
}
...
}
MyGlobalMethodSecurityConfig.java
package sample.spring.security;
...
import org.springframework.security.acls.jdbc.JdbcMutableAclService;
...
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class MyGlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
...
@Bean
public AclService aclService(DataSource dataSource, LookupStrategy lookupStrategy, AclCache aclCache) {
return new JdbcMutableAclService(dataSource, lookupStrategy, aclCache);
}
...
}
Zugriff zum Ausführen von "MyAclServlet".
Ausgabe der Serverkonsole
acl = AclImpl[
id: 1;
objectIdentity: org.springframework.security.acls.domain.ObjectIdentityImpl[
Type: sample.spring.security.domain.Foo;
Identifier: 10
];
owner: PrincipalSid[
foo
];
no ACEs;
inheriting: true;
parent: Null;
aclAuthorizationStrategy: org.springframework.security.acls.domain.AclAuthorizationStrategyImpl@2c7d9da4;
permissionGrantingStrategy: org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy@634b81ac
]
[ACL_SID]
{ID=1, PRINCIPAL=true, SID=foo}
[ACL_CLASS]
{ID=1, CLASS=sample.spring.security.domain.Foo}
[ACL_OBJECT_IDENTITY]
{ID=1, OBJECT_ID_CLASS=1, OBJECT_ID_IDENTITY=10, PARENT_OBJECT=null, OWNER_SID=1, ENTRIES_INHERITING=true}
[ACL_ENTRY]
* Die Ausgabe von Acl wird tatsächlich in einer Zeile ausgegeben, aber Zeilenumbrüche werden hinzugefügt, um die Anzeige zu vereinfachen </ font>
--Annotationsbasierte deklarative Transaktionen sind aktiviert, da Sie die Transaktion beim Aktualisieren der ACL-Tabelle steuern müssen.
MyAclSampleService.java
package sample.spring.security.service;
...
import org.springframework.transaction.annotation.Transactional;
...
@Transactional
public class MyAclSampleService {
...
@ Transactional
notierennamespace
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans ...
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
...
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<tx:annotation-driven />
...
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
</bean>
...
<annotationsgesteuert>
Java Configuration
MySpringSecurityConfig.java
...
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
...
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
...
@EnableTransactionManagement
...
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
...
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
namespace
applicationContext.xml
<bean id="aclService" class="org.springframework.security.acls.jdbc.JdbcMutableAclService">
<constructor-arg ref="dataSource" />
<constructor-arg ref="lookupStrategy" />
<constructor-arg ref="aclCache" />
</bean>
Java Configuration
MyGlobalMethodSecurityConfig.java
import org.springframework.security.acls.jdbc.JdbcMutableAclService;
...
@Bean
public AclService aclService(DataSource dataSource, LookupStrategy lookupStrategy, AclCache aclCache) {
return new JdbcMutableAclService(dataSource, lookupStrategy, aclCache);
}
MyAclSampleService.java
package sample.spring.security.service;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.MutableAclService;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.transaction.annotation.Transactional;
import sample.spring.security.domain.Foo;
@Transactional
public class MyAclSampleService {
private MutableAclService aclService;
public MyAclSampleService(MutableAclService aclService) {
this.aclService = aclService;
}
public void createObjectIdentity() {
ObjectIdentity objectIdentity = new ObjectIdentityImpl(Foo.class, 10L);
MutableAcl acl = this.aclService.createAcl(objectIdentity);
System.out.println("acl = " + acl);
}
}
--Erstellen Sie ein Objekt mit ObjectIdentity
( ObjectIdentityImpl
)
ID
)ACL_OBJECT_IDENTITY
gespeichert, wenn createAcl ()
ausgeführt wird.
--ACL_CLASS
wird auch zusammen erstellt, wenn die Informationen nicht vorhanden sindMutableAcl
Ausgabe der Serverkonsole
[ACL_SID]
{ID=1, PRINCIPAL=true, SID=foo}
[ACL_CLASS]
{ID=1, CLASS=sample.spring.security.domain.Foo}
[ACL_OBJECT_IDENTITY]
{ID=1, OBJECT_ID_CLASS=1, OBJECT_ID_IDENTITY=10, PARENT_OBJECT=null, OWNER_SID=1, ENTRIES_INHERITING=true}
{ID=2, OBJECT_ID_CLASS=1, OBJECT_ID_IDENTITY=11, PARENT_OBJECT=null, OWNER_SID=1, ENTRIES_INHERITING=true}
[ACL_ENTRY]
createAcl ()
von MutableAclService
ausgeführt wird.ACL-Informationen werden in der folgenden Klassenstruktur modelliert.
ObjectIdentity
Acl
AccessControlEntry
Permission
Sid
Wenn "createAcl ()" von "MutableAclService" ausgeführt wird, werden "Acl", "AccessControlEntry", "Permission" und "Sid" in der Form konstruiert, die der durch das Argument angegebenen "ObjectIdentity" zugeordnet ist.
MyAclSampleService.java
package sample.spring.security.service;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.model.Acl;
...
public class MyAclSampleService {
private MutableAclService aclService;
...
public void createObjectIdentity() {
...
}
public void findAcl() {
ObjectIdentity objectIdentity = new ObjectIdentityImpl(Foo.class, 10L);
Acl acl = aclService.readAclById(objectIdentity);
System.out.println("acl = " + acl);
}
}
MyAclServlet.java
package sample.spring.security.servlet;
...
@WebServlet("/acl")
public class MyAclServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
MyAclSampleService service = this.findServiceBean(req, MyAclSampleService.class);
service.createObjectIdentity();
this.printTables(req);
service.findAcl();
}
...
}
Ausgabe der Serverkonsole (createObjectIdeneity)()Ausgabe entfällt)
acl = AclImpl[
id: 1;
objectIdentity: org.springframework.security.acls.domain.ObjectIdentityImpl[
Type: sample.spring.security.domain.Foo;
Identifier: 10
];
owner: PrincipalSid[
foo
];
no ACEs;
inheriting: true;
parent: Null;
aclAuthorizationStrategy: org.springframework.security.acls.domain.AclAuthorizationStrategyImpl@2c7d9da4;
permissionGrantingStrategy: org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy@634b81ac
]
MyAclSampleService.java
public void findAcl() {
ObjectIdentity objectIdentity = new ObjectIdentityImpl(Foo.class, 10L);
Acl acl = aclService.readAclById(objectIdentity);
System.out.println("acl = " + acl);
}
--AclService
bietet eine Methode zur Suche nach Acl
MyAclSampleService.java
package sample.spring.security.service;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.domain.GrantedAuthoritySid;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.security.acls.model.AccessControlEntry;
import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.MutableAclService;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.transaction.annotation.Transactional;
import sample.spring.security.domain.Foo;
import java.util.List;
@Transactional
public class MyAclSampleService {
private MutableAclService aclService;
...
public void createObjectIdentity() {
...
}
public void findAcl() {
...
}
public void addPermission() {
//Suchen Sie nach der zu aktualisierenden ACL und
ObjectIdentity objectIdentity = new ObjectIdentityImpl(Foo.class, 10L);
MutableAcl acl = (MutableAcl) aclService.readAclById(objectIdentity);
//Behörde"HOGE_AUTHORITY"Gewähren Sie CREATE-Berechtigungen für
List<AccessControlEntry> entries = acl.getEntries();
GrantedAuthoritySid grantedAuthoritySid = new GrantedAuthoritySid(new SimpleGrantedAuthority("HOGE_AUTHORITY"));
acl.insertAce(entries.size(), BasePermission.CREATE, grantedAuthoritySid, true);
//Schulleiter"test_user"Erteilen Sie WRITE die Erlaubnis zu
PrincipalSid principalSid = new PrincipalSid("test_user");
acl.insertAce(entries.size(), BasePermission.WRITE, principalSid, true);
//ACL-Änderungen speichern
this.aclService.updateAcl(acl);
System.out.println("acl = " + acl);
}
}
MyAclServlet.java
package sample.spring.security.servlet;
...
@WebServlet("/acl")
public class MyAclServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
MyAclSampleService service = this.findServiceBean(req, MyAclSampleService.class);
service.createObjectIdentity();
this.printTables(req);
service.findAcl();
service.addPermission();
this.printTables(req);
}
...
}
Ausgabe der Serverkonsole
★ Vor dem Hinzufügen von Berechtigungen
acl = AclImpl[
id: 1;
objectIdentity: org.springframework.security.acls.domain.ObjectIdentityImpl[
Type: sample.spring.security.domain.Foo;
Identifier: 10
];
owner: PrincipalSid[
foo
];
no ACEs;
inheriting: true;
parent: Null;
aclAuthorizationStrategy: org.springframework.security.acls.domain.AclAuthorizationStrategyImpl@162ff71c;
permissionGrantingStrategy: org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy@742976d3
]
[ACL_SID]
{ID=1, PRINCIPAL=true, SID=foo}
[ACL_CLASS]
{ID=1, CLASS=sample.spring.security.domain.Foo}
[ACL_OBJECT_IDENTITY]
{ID=1, OBJECT_ID_CLASS=1, OBJECT_ID_IDENTITY=10, PARENT_OBJECT=null, OWNER_SID=1, ENTRIES_INHERITING=true}
[ACL_ENTRY]
...
★ Nach dem Hinzufügen von Berechtigungen
acl = AclImpl[
id: 1;
objectIdentity: org.springframework.security.acls.domain.ObjectIdentityImpl[
Type: sample.spring.security.domain.Foo;
Identifier: 10
];
owner: PrincipalSid[
foo
];
AccessControlEntryImpl[
id: null;
granting: true;
sid: PrincipalSid[
test_user
];
permission: BasePermission[
..............................W.=2
];
auditSuccess: false;
auditFailure: false
]
AccessControlEntryImpl[
id: null;
granting: true;
sid: GrantedAuthoritySid[
HOGE_AUTHORITY
];
permission: BasePermission[
.............................C..=4
];
auditSuccess: false;
auditFailure: false
]
inheriting: true;
parent: Null;
aclAuthorizationStrategy: org.springframework.security.acls.domain.AclAuthorizationStrategyImpl@162ff71c;
permissionGrantingStrategy: org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy@742976d3
]
[ACL_SID]
{ID=1, PRINCIPAL=true, SID=foo}
{ID=2, PRINCIPAL=true, SID=test_user}
{ID=3, PRINCIPAL=false, SID=HOGE_AUTHORITY}
[ACL_CLASS]
{ID=1, CLASS=sample.spring.security.domain.Foo}
[ACL_OBJECT_IDENTITY]
{ID=1, OBJECT_ID_CLASS=1, OBJECT_ID_IDENTITY=10, PARENT_OBJECT=null, OWNER_SID=1, ENTRIES_INHERITING=true}
[ACL_ENTRY]
{ID=1, ACL_OBJECT_IDENTITY=1, ACE_ORDER=0, SID=2, MASK=2, GRANTING=true, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
{ID=2, ACL_OBJECT_IDENTITY=1, ACE_ORDER=1, SID=3, MASK=4, GRANTING=true, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
MyAclSampleService.java
public void addPermission() {
//Suchen Sie nach der zu aktualisierenden ACL und
ObjectIdentity objectIdentity = new ObjectIdentityImpl(Foo.class, 10L);
MutableAcl acl = (MutableAcl) aclService.readAclById(objectIdentity);
//Behörde"HOGE_AUTHORITY"Gewähren Sie CREATE-Berechtigungen für
List<AccessControlEntry> entries = acl.getEntries();
GrantedAuthoritySid grantedAuthoritySid = new GrantedAuthoritySid(new SimpleGrantedAuthority("HOGE_AUTHORITY"));
acl.insertAce(entries.size(), BasePermission.CREATE, grantedAuthoritySid, true);
//Schulleiter"test_user"Erteilen Sie WRITE die Erlaubnis zu
PrincipalSid principalSid = new PrincipalSid("test_user");
acl.insertAce(entries.size(), BasePermission.WRITE, principalSid, true);
//ACL-Änderungen speichern
this.aclService.updateAcl(acl);
System.out.println("acl = " + acl);
}
AccessControlEntry
) werden in Acl
als List
gespeichert und an das erste Argument der add (int, E)
-Methode übergeben.Permission
kann die in der Implementierungsklasse BasePermission
definierten Konstanten angeben
--Sid
gibt GrantedAuthoritySid
oder PrincipalSid
anPrincipalSid
, um Principals Berechtigungen zuzuweisenMyAclSampleService.java
package sample.spring.security.service;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.domain.GrantedAuthoritySid;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.MutableAclService;
import org.springframework.security.acls.model.NotFoundException;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.transaction.annotation.Transactional;
import sample.spring.security.domain.Foo;
@Transactional
public class MyAclSampleService {
private MutableAclService aclService;
public MyAclSampleService(MutableAclService aclService) {
this.aclService = aclService;
}
public void addPermission() {
ObjectIdentity objectIdentity = new ObjectIdentityImpl(Foo.class, 10L);
try {
this.aclService.readAclById(objectIdentity);
} catch (NotFoundException e) {
MutableAcl acl = this.aclService.createAcl(objectIdentity);
GrantedAuthoritySid deniedRead = new GrantedAuthoritySid(new SimpleGrantedAuthority("DENIED_READ"));
acl.insertAce(0, BasePermission.READ, deniedRead, false);
GrantedAuthoritySid permitRead = new GrantedAuthoritySid(new SimpleGrantedAuthority("PERMIT_READ"));
acl.insertAce(1, BasePermission.READ, permitRead, true);
this.aclService.updateAcl(acl);
}
}
@PreAuthorize("hasPermission(#foo, read)")
public void read(Foo foo) {
System.out.println("read(" + foo + ")");
}
}
DENIED_READ
auf 0
gesetzt werden, damit es an erster Stelle steht.package sample.spring.security.servlet;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import sample.spring.security.domain.Foo;
import sample.spring.security.service.MyAclSampleService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@WebServlet("/acl")
public class MyAclServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.printPrincipal();
MyAclSampleService service = this.findServiceBean(req, MyAclSampleService.class);
service.addPermission();
this.printTables(req);
try {
service.read(new Foo(10L));
} catch (AccessDeniedException e) {
System.out.println(e.getMessage());
}
}
...
}
printPrincipal ()
)addPermission ()
)printTables ()
)Implementierung
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
...>
...
<sec:authentication-manager>
<sec:authentication-provider>
<sec:user-service>
<sec:user name="foo" password="foo" authorities="PERMIT_READ" />
<sec:user name="bar" password="bar" authorities="PERMIT_READ,DENIED_READ" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
</beans>
foo
und bar
PERMIT_READ
für den Benutzer foo
Melden Sie sich als foo
Benutzer an und greifen Sie / acl
zu.
Ausgabe der Serverkonsole
name=foo
authorities=PERMIT_READ
[ACL_SID]
{ID=1, PRINCIPAL=true, SID=foo}
{ID=2, PRINCIPAL=false, SID=DENIED_READ}
{ID=3, PRINCIPAL=false, SID=PERMIT_READ}
[ACL_CLASS]
{ID=1, CLASS=sample.spring.security.domain.Foo}
[ACL_OBJECT_IDENTITY]
{ID=1, OBJECT_ID_CLASS=1, OBJECT_ID_IDENTITY=10, PARENT_OBJECT=null, OWNER_SID=1, ENTRIES_INHERITING=true}
[ACL_ENTRY]
{ID=1, ACL_OBJECT_IDENTITY=1, ACE_ORDER=0, SID=2, MASK=1, GRANTING=false, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
{ID=2, ACL_OBJECT_IDENTITY=1, ACE_ORDER=1, SID=3, MASK=1, GRANTING=true, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
read(Foo{id=10})
Die Methode read () kann ausgeführt werden
Melden Sie sich dann als "bar" -Benutzer an und greifen Sie auf "/ acl" zu.
Ausgabe der Serverkonsole
name=bar
authorities=DENIED_READ, PERMIT_READ
[ACL_SID]
{ID=1, PRINCIPAL=true, SID=foo}
{ID=2, PRINCIPAL=false, SID=DENIED_READ}
{ID=3, PRINCIPAL=false, SID=PERMIT_READ}
[ACL_CLASS]
{ID=1, CLASS=sample.spring.security.domain.Foo}
[ACL_OBJECT_IDENTITY]
{ID=1, OBJECT_ID_CLASS=1, OBJECT_ID_IDENTITY=10, PARENT_OBJECT=null, OWNER_SID=1, ENTRIES_INHERITING=true}
[ACL_ENTRY]
{ID=1, ACL_OBJECT_IDENTITY=1, ACE_ORDER=0, SID=2, MASK=1, GRANTING=false, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
{ID=2, ACL_OBJECT_IDENTITY=1, ACE_ORDER=1, SID=3, MASK=1, GRANTING=true, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
Access is denied
Zugriff wurde verweigert.
MyAclSampleService.java
MutableAcl acl = this.aclService.createAcl(objectIdentity);
GrantedAuthoritySid deniedRead = new GrantedAuthoritySid(new SimpleGrantedAuthority("DENIED_READ"));
acl.insertAce(0, BasePermission.READ, deniedRead, false);
GrantedAuthoritySid permitRead = new GrantedAuthoritySid(new SimpleGrantedAuthority("PERMIT_READ"));
acl.insertAce(1, BasePermission.READ, permitRead, true);
this.aclService.updateAcl(acl);
applicationContext.xml
<sec:user name="foo" password="foo" authorities="PERMIT_READ" />
<sec:user name="bar" password="bar" authorities="PERMIT_READ,DENIED_READ" />
--ACE_ORDER
scheint angewendet zu werden, wobei der Bestellung zuerst Priorität eingeräumt wird
――Wenn ich diesen Mechanismus zum ersten Mal sah (Erlaubnis verweigern und "ACE" bestellen), fiel mir nicht viel Nutzen ein.
Nicht jeder kann die ACL aktualisieren.
src/main/resources/sql/insert_acl_tables.sql
INSERT INTO ACL_CLASS (ID, CLASS)
VALUES (100, 'sample.spring.security.domain.Foo');
INSERT INTO ACL_SID (ID, PRINCIPAL, SID)
VALUES (9, true, 'hoge');
INSERT INTO ACL_SID (ID, PRINCIPAL, SID)
VALUES (19, true, 'admin');
INSERT INTO ACL_OBJECT_IDENTITY (ID, OBJECT_ID_CLASS, OBJECT_ID_IDENTITY, PARENT_OBJECT, OWNER_SID, ENTRIES_INHERITING)
VALUES (1000, 100, 10, NULL, 9, true);
INSERT INTO ACL_ENTRY (ID, ACL_OBJECT_IDENTITY, ACE_ORDER, SID, MASK, GRANTING, AUDIT_SUCCESS, AUDIT_FAILURE)
VALUES (10000, 1000, 0, 19, 16, true, false, false); --admin user admin(16)Erlaubnis erteilen
--Erstelle ACL_OBJECT_IDENTITY
für Foo
Objekt mit ID = 10
--Stellen Sie den "Hoge" -Prinzipal als Eigentümer ein
--Grant Administration
Berechtigungen zu Admin
Principals
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
...>
...
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="classpath:/sql/create_acl_tables.sql" />
<jdbc:script location="classpath:/sql/insert_acl_tables.sql" />
</jdbc:embedded-database>
...
<bean id="aclAuthorizationStrategy" class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
<constructor-arg>
<list>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="PERMISSION_MANAGER"/>
</bean>
</list>
</constructor-arg>
</bean>
...
<sec:authentication-manager>
<sec:authentication-provider>
<sec:user-service>
<sec:user name="hoge" password="hoge" authorities="" />
<sec:user name="fuga" password="fuga" authorities="" />
<sec:user name="piyo" password="piyo" authorities="PERMISSION_MANAGER" />
<sec:user name="admin" password="admin" authorities="" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
</beans>
PERMISSION_MANAGER
im Konstruktorargument von AclAuthorizationStrategyImpl
--hoge
, fuga
, admin
Benutzer hat keine Berechtigungen
--Grant PERMISSION_MANAGER
Privilegien nur für Piyo
BenutzerMyAclSampleService.java
package sample.spring.security.service;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.domain.GrantedAuthoritySid;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.security.acls.model.AlreadyExistsException;
import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.MutableAclService;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.transaction.annotation.Transactional;
import sample.spring.security.domain.Foo;
@Transactional
public class MyAclSampleService {
private MutableAclService aclService;
public MyAclSampleService(MutableAclService aclService) {
this.aclService = aclService;
}
public void addPermission() {
ObjectIdentity objectIdentity = new ObjectIdentityImpl(Foo.class, 10L);
MutableAcl acl = (MutableAcl) this.aclService.readAclById(objectIdentity);
acl.insertAce(
acl.getEntries().size(),
BasePermission.READ,
new GrantedAuthoritySid(new SimpleGrantedAuthority("test")),
true
);
this.aclService.updateAcl(acl);
}
}
--Suchen nach einem Foo
-Objekt mit id = 10
und Hinzufügen von Berechtigungen mit insertAce ()
MyAclServlet.java
package sample.spring.security.servlet;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.acls.model.NotFoundException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import sample.spring.security.service.MyAclSampleService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@WebServlet("/acl")
public class MyAclServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
MyAclSampleService service = this.findServiceBean(req, MyAclSampleService.class);
this.printPrincipal();
this.printTables(req);
try {
System.out.println("service.addPermission()");
service.addPermission();
this.printTables(req);
} catch (AccessDeniedException | NotFoundException e) {
System.out.println("e.class = " + e.getClass() + ", message = " + e.getMessage());
}
}
...
}
addPermission ()
eine Ausnahme auftritt, werden diese Informationen ausgegeben.** Beim Zugriff als Hoge-Benutzer **
Ausgabe der Serverkonsole
★ Benutzerinformationen
name=hoge
authorities=
★ Status der Tabelle vor dem Update
[ACL_SID]
{ID=9, PRINCIPAL=true, SID=hoge}
{ID=19, PRINCIPAL=true, SID=admin}
[ACL_CLASS]
{ID=100, CLASS=sample.spring.security.domain.Foo}
[ACL_OBJECT_IDENTITY]
{ID=1000, OBJECT_ID_CLASS=100, OBJECT_ID_IDENTITY=10, PARENT_OBJECT=null, OWNER_SID=9, ENTRIES_INHERITING=true}
[ACL_ENTRY]
{ID=10000, ACL_OBJECT_IDENTITY=1000, ACE_ORDER=0, SID=19, MASK=16, GRANTING=true, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
★ Methodenausführung
service.addPermission()
★ Status der Tabelle nach dem Update
[ACL_SID]
{ID=9, PRINCIPAL=true, SID=hoge}
{ID=19, PRINCIPAL=true, SID=admin}
{ID=20, PRINCIPAL=false, SID=test}
[ACL_CLASS]
{ID=100, CLASS=sample.spring.security.domain.Foo}
[ACL_OBJECT_IDENTITY]
{ID=1000, OBJECT_ID_CLASS=100, OBJECT_ID_IDENTITY=10, PARENT_OBJECT=null, OWNER_SID=9, ENTRIES_INHERITING=true}
[ACL_ENTRY]
{ID=10001, ACL_OBJECT_IDENTITY=1000, ACE_ORDER=0, SID=19, MASK=16, GRANTING=true, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
{ID=10002, ACL_OBJECT_IDENTITY=1000, ACE_ORDER=1, SID=20, MASK=1, GRANTING=true, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
** Beim Zugriff als Fuga-Benutzer **
Ausgabe der Serverkonsole
★ Benutzerinformationen
name=fuga
authorities=
★ Status der Tabelle vor dem Update
[ACL_SID]
{ID=9, PRINCIPAL=true, SID=hoge}
{ID=19, PRINCIPAL=true, SID=admin}
[ACL_CLASS]
{ID=100, CLASS=sample.spring.security.domain.Foo}
[ACL_OBJECT_IDENTITY]
{ID=1000, OBJECT_ID_CLASS=100, OBJECT_ID_IDENTITY=10, PARENT_OBJECT=null, OWNER_SID=9, ENTRIES_INHERITING=true}
[ACL_ENTRY]
{ID=10000, ACL_OBJECT_IDENTITY=1000, ACE_ORDER=0, SID=19, MASK=16, GRANTING=true, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
★ Methodenausführung
service.addPermission()
★ Fehlerinformationen
e.class = class org.springframework.security.acls.model.NotFoundException, message = Unable to locate a matching ACE for passed permissions and SIDs
NotFoundException
) wurde ausgelöst** Beim Zugriff als Piyo-Benutzer **
Ausgabe der Serverkonsole
★ Benutzerinformationen
name=piyo
authorities=PERMISSION_MANAGER
★ Status der Tabelle vor dem Update
[ACL_SID]
{ID=9, PRINCIPAL=true, SID=hoge}
{ID=19, PRINCIPAL=true, SID=admin}
[ACL_CLASS]
{ID=100, CLASS=sample.spring.security.domain.Foo}
[ACL_OBJECT_IDENTITY]
{ID=1000, OBJECT_ID_CLASS=100, OBJECT_ID_IDENTITY=10, PARENT_OBJECT=null, OWNER_SID=9, ENTRIES_INHERITING=true}
[ACL_ENTRY]
{ID=10000, ACL_OBJECT_IDENTITY=1000, ACE_ORDER=0, SID=19, MASK=16, GRANTING=true, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
★ Methodenausführung
service.addPermission()
★ Status der Tabelle nach dem Update
[ACL_SID]
{ID=9, PRINCIPAL=true, SID=hoge}
{ID=19, PRINCIPAL=true, SID=admin}
{ID=20, PRINCIPAL=false, SID=test}
[ACL_CLASS]
{ID=100, CLASS=sample.spring.security.domain.Foo}
[ACL_OBJECT_IDENTITY]
{ID=1000, OBJECT_ID_CLASS=100, OBJECT_ID_IDENTITY=10, PARENT_OBJECT=null, OWNER_SID=9, ENTRIES_INHERITING=true}
[ACL_ENTRY]
{ID=10001, ACL_OBJECT_IDENTITY=1000, ACE_ORDER=0, SID=19, MASK=16, GRANTING=true, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
{ID=10002, ACL_OBJECT_IDENTITY=1000, ACE_ORDER=1, SID=20, MASK=1, GRANTING=true, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
** Beim Zugriff als Administrator **
Ausgabe der Serverkonsole
★ Benutzerinformationen
name=admin
authorities=
★ Status der Tabelle vor dem Update
[ACL_SID]
{ID=9, PRINCIPAL=true, SID=hoge}
{ID=19, PRINCIPAL=true, SID=admin}
[ACL_CLASS]
{ID=100, CLASS=sample.spring.security.domain.Foo}
[ACL_OBJECT_IDENTITY]
{ID=1000, OBJECT_ID_CLASS=100, OBJECT_ID_IDENTITY=10, PARENT_OBJECT=null, OWNER_SID=9, ENTRIES_INHERITING=true}
[ACL_ENTRY]
{ID=10000, ACL_OBJECT_IDENTITY=1000, ACE_ORDER=0, SID=19, MASK=16, GRANTING=true, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
★ Methodenausführung
service.addPermission()
★ Status der Tabelle nach dem Update
[ACL_SID]
{ID=9, PRINCIPAL=true, SID=hoge}
{ID=19, PRINCIPAL=true, SID=admin}
{ID=20, PRINCIPAL=false, SID=test}
[ACL_CLASS]
{ID=100, CLASS=sample.spring.security.domain.Foo}
[ACL_OBJECT_IDENTITY]
{ID=1000, OBJECT_ID_CLASS=100, OBJECT_ID_IDENTITY=10, PARENT_OBJECT=null, OWNER_SID=9, ENTRIES_INHERITING=true}
[ACL_ENTRY]
{ID=10001, ACL_OBJECT_IDENTITY=1000, ACE_ORDER=0, SID=19, MASK=16, GRANTING=true, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
{ID=10002, ACL_OBJECT_IDENTITY=1000, ACE_ORDER=1, SID=20, MASK=1, GRANTING=true, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
AclAuthorizationStrategyImpl
angegebenen Berechtigungen verfügenEs gibt drei Arten von ACL-Updates:
--Allgemeines
Die Methoden zum Aktualisieren der ACL sind wie folgt klassifiziert.
Methode | Aktualisierungstyp |
---|---|
insertAce() |
Allgemeines |
updateAce() |
Allgemeines |
deleteAce() |
Allgemeines |
setParent() |
Allgemeines |
setEntriesInheriting() |
Allgemeines |
setOwner() |
Im Besitz |
updateAuditing() |
Prüfung |
Diese drei Typen werden übrigens in der Schnittstelle "AclAuthorizationStrategy" definiert.
AclAuthorizationStrategy.java
public interface AclAuthorizationStrategy {
int CHANGE_OWNERSHIP = 0;Im Besitz
int CHANGE_AUDITING = 1;Prüfung
int CHANGE_GENERAL = 2;Allgemeines
applicationContext.xml
<bean id="aclAuthorizationStrategy" class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
<constructor-arg>
<list>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="PERMISSION_MANAGER"/>
</bean>
</list>
</constructor-arg>
</bean>
Im obigen Beispiel wird nur die Berechtigung "PERMISSION_MANAGER" angegeben. In diesem Fall sind alle Arten von Aktualisierungen (allgemein, im Besitz, geprüft) zulässig, wenn Sie über diese Berechtigung verfügen.
Wenn Sie steuern möchten, dass ●● für das "allgemeine" Update erforderlich ist, ist ▲▲ für das "eigene" Update und ★★ für das "Audit" wie folgt erforderlich. Definieren Sie eine Bohne in.
applicationContext.xml
<bean id="aclAuthorizationStrategy" class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
<constructor-arg>
<list>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="PERMISSION_MANAGER_OWNERSHIP"/>
</bean>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="PERMISSION_MANAGER_AUDIT"/>
</bean>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg value="PERMISSION_MANAGER_GENERAL"/>
</bean>
</list>
</constructor-arg>
</bean>
Im obigen Beispiel wurde eine "NotFoundException" ausgelöst, wenn das Update abgelehnt wurde.
Es ist nicht wahr, dass "NotFoundException" immer ausgelöst wird, wenn es nicht erlaubt ist. Wenn für die zu aktualisierende ACL die Berechtigung "Administration" auf "Verweigern" gesetzt ist, wird eine "AccessDeniedException" ausgelöst.
Dies ist tatsächlich ein ** Fehler **, und in beiden Fällen ist es richtig, eine "AccessDeniedException" auszulösen.
Eine Suche nach einem Problem auf GitHub zeigt, dass dieser Fehler aufgetreten ist. Ab dem 09. Juli 2017 bleibt dieses Problem jedoch offen und scheint nicht behoben zu sein. Es scheint, dass dieses Problem im Jahr 2009 erkannt wurde, sodass es vollständig vernachlässigt wurde (nicht darauf beschränkt, alle ACL-bezogenen Probleme wurden lange Zeit vernachlässigt und werden möglicherweise nicht viel gewartet. Unbekannt).
Darüber hinaus bezieht sich die Berechtigungsprüfung für die ACL-Aktualisierung bei Verwendung von Rollenhierarchien nicht auf die übergeordnete Rolle [https://github.com/spring-projects/spring-security/issues]. Bugs wie / 4186) wurden ausgelöst (auch lange Zeit unbeaufsichtigt gelassen).
Wenn Sie diesen Bereich mit korrektem Betrieb verwenden möchten, müssen Sie das vorhandene "AclAuthorizationStrategyImpl" kopieren, eine eigene Implementierungsklasse erstellen, die das Problem behebt, und es anstelle von "AclAuthorizationStrategyImpl" verwenden. (Oder ziehen Sie die geänderte Version an die Kopffamilie)
"ACL_OBJECT_IDENTITY" kann eine Vererbungsbeziehung haben.
Hello World
insert_acl_tables.sql
INSERT INTO ACL_CLASS (ID, CLASS)
VALUES (100, 'sample.spring.security.domain.Foo');
INSERT INTO ACL_SID (ID, PRINCIPAL, SID)
VALUES (9, true, 'hoge');
INSERT INTO ACL_SID (ID, PRINCIPAL, SID)
VALUES (98, false, 'READONLY');
INSERT INTO ACL_OBJECT_IDENTITY (ID, OBJECT_ID_CLASS, OBJECT_ID_IDENTITY, PARENT_OBJECT, OWNER_SID, ENTRIES_INHERITING)
VALUES (1000, 100, 44, NULL, 9, false);
INSERT INTO ACL_OBJECT_IDENTITY (ID, OBJECT_ID_CLASS, OBJECT_ID_IDENTITY, PARENT_OBJECT, OWNER_SID, ENTRIES_INHERITING)
VALUES (1001, 100, 45, NULL, 9, false);
INSERT INTO ACL_OBJECT_IDENTITY (ID, OBJECT_ID_CLASS, OBJECT_ID_IDENTITY, PARENT_OBJECT, OWNER_SID, ENTRIES_INHERITING)
VALUES (1002, 100, 46, 1000, 9, false);
INSERT INTO ACL_OBJECT_IDENTITY (ID, OBJECT_ID_CLASS, OBJECT_ID_IDENTITY, PARENT_OBJECT, OWNER_SID, ENTRIES_INHERITING)
VALUES (1003, 100, 47, 1000, 9, true);
INSERT INTO ACL_ENTRY (ID, ACL_OBJECT_IDENTITY, ACE_ORDER, SID, MASK, GRANTING, AUDIT_SUCCESS, AUDIT_FAILURE)
VALUES (10, 1000, 0, 98, 1, true, false, false);
ACL_OBJECT_IDENTITY
von id = 44 ... 47
--Granting "Lese" -Zulassung zu "READONLY" -Erlaubnis nur für "id = 44"
--id = 45
gibt kein übergeordnetes Objekt usw. an.
--id = 46
gibt nur die ID des übergeordneten Objekts mit PARENT_OBJECT
an (ENTRIES_INHERITING
ist false
)
--id = 47
setzt ENTRIES_INHERITING
nach Angabe des übergeordneten Objekts auf true
MyAclSampleService.java
package sample.spring.security.service;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import sample.spring.security.domain.Foo;
@Transactional
public class MyAclSampleService {
@PreAuthorize("hasPermission(#foo, read)")
public void read(Foo foo) {
System.out.println("read(" + foo + ")");
}
}
--Überprüfen Sie, ob Sie Leseberechtigungen für das Foo-Objekt haben, das Sie als Argument erhalten
MyAclServlet.java
package sample.spring.security.servlet;
...
import sample.spring.security.domain.Foo;
import sample.spring.security.service.MyAclSampleService;
@WebServlet("/acl")
public class MyAclServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.printPrincipal();
this.printTables(req);
this.callServiceLogic(req, 44L);
this.callServiceLogic(req, 45L);
this.callServiceLogic(req, 46L);
this.callServiceLogic(req, 47L);
}
private void callServiceLogic(HttpServletRequest req, long id) {
try {
System.out.println("id=" + id);
MyAclSampleService service = this.findServiceBean(req);
Foo foo = new Foo(id);
service.read(foo);
} catch (AccessDeniedException e) {
System.out.println("AccessDeniedException : " + e.getMessage());
}
}
...
}
--Erstelle ein Foo
Objekt mit id = 44 ... 47
und führe dieread ()
Methode von MyAclSampleService
aus
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
...>
...
<sec:authentication-manager>
<sec:authentication-provider>
<sec:user-service>
<sec:user name="foo" password="foo" authorities="READONLY" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
</beans>
--Grant READONLY
Privilegien für den foo
Benutzer
Melden Sie sich als foo
Benutzer an und greifen Sie / acl
zu.
Ausgabe der Serverkonsole
name=foo
authorities=READONLY
[ACL_SID]
{ID=9, PRINCIPAL=true, SID=hoge}
{ID=98, PRINCIPAL=false, SID=READONLY}
[ACL_CLASS]
{ID=100, CLASS=sample.spring.security.domain.Foo}
[ACL_OBJECT_IDENTITY]
{ID=1000, OBJECT_ID_CLASS=100, OBJECT_ID_IDENTITY=44, PARENT_OBJECT=null, OWNER_SID=9, ENTRIES_INHERITING=false}
{ID=1001, OBJECT_ID_CLASS=100, OBJECT_ID_IDENTITY=45, PARENT_OBJECT=null, OWNER_SID=9, ENTRIES_INHERITING=false}
{ID=1002, OBJECT_ID_CLASS=100, OBJECT_ID_IDENTITY=46, PARENT_OBJECT=1000, OWNER_SID=9, ENTRIES_INHERITING=false}
{ID=1003, OBJECT_ID_CLASS=100, OBJECT_ID_IDENTITY=47, PARENT_OBJECT=1000, OWNER_SID=9, ENTRIES_INHERITING=true}
[ACL_ENTRY]
{ID=10, ACL_OBJECT_IDENTITY=1000, ACE_ORDER=0, SID=98, MASK=1, GRANTING=true, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
id=44
read(Foo{id=44})
id=45
AccessDeniedException : Access is denied
id=46
AccessDeniedException : Access is denied
id=47
read(Foo{id=47})
insert_acl_tables.sql
...
INSERT INTO ACL_OBJECT_IDENTITY (ID, OBJECT_ID_CLASS, OBJECT_ID_IDENTITY, PARENT_OBJECT, OWNER_SID, ENTRIES_INHERITING)
VALUES (1000, 100, 44, NULL, 9, false);
INSERT INTO ACL_OBJECT_IDENTITY (ID, OBJECT_ID_CLASS, OBJECT_ID_IDENTITY, PARENT_OBJECT, OWNER_SID, ENTRIES_INHERITING)
VALUES (1001, 100, 45, NULL, 9, false);
INSERT INTO ACL_OBJECT_IDENTITY (ID, OBJECT_ID_CLASS, OBJECT_ID_IDENTITY, PARENT_OBJECT, OWNER_SID, ENTRIES_INHERITING)
VALUES (1002, 100, 46, 1000, 9, false);
INSERT INTO ACL_OBJECT_IDENTITY (ID, OBJECT_ID_CLASS, OBJECT_ID_IDENTITY, PARENT_OBJECT, OWNER_SID, ENTRIES_INHERITING)
VALUES (1003, 100, 47, 1000, 9, true);
PARENT_OBJECT
auf ID
des übergeordneten ACL_OBJECT_IDENTITY
ENTRIES_INHERITING
auf true
MyAclSampleService.java
package sample.spring.security.service;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.domain.GrantedAuthoritySid;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.MutableAclService;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.transaction.annotation.Transactional;
import sample.spring.security.domain.Foo;
@Transactional
public class MyAclSampleService {
private MutableAclService aclService;
public MyAclSampleService(MutableAclService aclService) {
this.aclService = aclService;
}
public void init() {
ObjectIdentityImpl parentId = new ObjectIdentityImpl(Foo.class, 44L);
MutableAcl parentAcl = this.aclService.createAcl(parentId);
parentAcl.insertAce(
parentAcl.getEntries().size(),
BasePermission.READ,
new GrantedAuthoritySid(new SimpleGrantedAuthority("READONLY")),
true
);
this.aclService.updateAcl(parentAcl);
ObjectIdentityImpl childId = new ObjectIdentityImpl(Foo.class, 45L);
MutableAcl childAcl = this.aclService.createAcl(childId);
childAcl.setParent(parentAcl);
this.aclService.updateAcl(childAcl);
}
}
python
package sample.spring.security.servlet;
...
@WebServlet("/acl")
public class MyAclServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
MyAclSampleService service = this.findServiceBean(req);
service.init();
this.printTables(req);
}
...
}
Zugriff auf / acl
Serverprotokollausgabe
[ACL_SID]
{ID=1, PRINCIPAL=true, SID=foo}
{ID=2, PRINCIPAL=false, SID=READONLY}
[ACL_CLASS]
{ID=1, CLASS=sample.spring.security.domain.Foo}
[ACL_OBJECT_IDENTITY]
{ID=1, OBJECT_ID_CLASS=1, OBJECT_ID_IDENTITY=44, PARENT_OBJECT=null, OWNER_SID=1, ENTRIES_INHERITING=true}
{ID=2, OBJECT_ID_CLASS=1, OBJECT_ID_IDENTITY=45, PARENT_OBJECT=1, OWNER_SID=1, ENTRIES_INHERITING=true}
[ACL_ENTRY]
{ID=1, ACL_OBJECT_IDENTITY=1, ACE_ORDER=0, SID=2, MASK=1, GRANTING=true, AUDIT_SUCCESS=false, AUDIT_FAILURE=false}
MyAclSampleService.java
public void init() {
ObjectIdentityImpl parentId = new ObjectIdentityImpl(Foo.class, 44L);
MutableAcl parentAcl = this.aclService.createAcl(parentId);
parentAcl.insertAce(
parentAcl.getEntries().size(),
BasePermission.READ,
new GrantedAuthoritySid(new SimpleGrantedAuthority("READONLY")),
true
);
this.aclService.updateAcl(parentAcl);
ObjectIdentityImpl childId = new ObjectIdentityImpl(Foo.class, 45L);
MutableAcl childAcl = this.aclService.createAcl(childId);
childAcl.setParent(parentAcl); //★ Eltern hier einstellen
this.aclService.updateAcl(childAcl);
}
ENTRIES_INHERITING
ist standardmäßig "true", wenn eine neue ACL erstellt wird. Daher muss diese beim Erstellen einer neuen ACL nicht angegeben werden (sie kann mit der Methode "setEntriesInheriting ()" festgelegt werden.)Es gibt einen Mechanismus zum Ausgeben der Informationen als Überwachungsprotokoll, wenn die Berechtigung erteilt oder verweigert wird.
Hello World
insert_acl_tables.sql
INSERT INTO ACL_CLASS (ID, CLASS)
VALUES (100, 'sample.spring.security.domain.Foo');
INSERT INTO ACL_SID (ID, PRINCIPAL, SID)
VALUES (9, true, 'hoge');
INSERT INTO ACL_SID (ID, PRINCIPAL, SID)
VALUES (98, false, 'READONLY');
INSERT INTO ACL_OBJECT_IDENTITY (ID, OBJECT_ID_CLASS, OBJECT_ID_IDENTITY, PARENT_OBJECT, OWNER_SID, ENTRIES_INHERITING)
VALUES (999, 100, 44, NULL, 9, false);
INSERT INTO ACL_ENTRY (ID, ACL_OBJECT_IDENTITY, ACE_ORDER, SID, MASK, GRANTING, AUDIT_SUCCESS, AUDIT_FAILURE)
VALUES (10, 999, 0, 98, 1, true, true, false);
INSERT INTO ACL_ENTRY (ID, ACL_OBJECT_IDENTITY, ACE_ORDER, SID, MASK, GRANTING, AUDIT_SUCCESS, AUDIT_FAILURE)
VALUES (11, 999, 1, 98, 2, false, false, true);
--Für id = 44
von Foo
die Berechtigungen" give read
"und" verweigert write
"für das Privileg" READONLY "festlegen. --
ACL_ENTRY in "Grant
read" ändert
AUDIT_SUCCESS in
true --
ACL_ENTRY in "Reject
write "setzt
AUDIT_FAILURE auf
true`
MyAclSampleService.java
package sample.spring.security.service;
import org.springframework.security.access.prepost.PreAuthorize;
import sample.spring.security.domain.Foo;
public class MyAclSampleService {
@PreAuthorize("hasPermission(#foo, read)")
public void read(Foo foo) {
System.out.println(foo);
}
@PreAuthorize("hasPermission(#foo, write)")
public void write(Foo foo) {
System.out.println(foo);
}
}
MyAclServlet.java
package sample.spring.security.servlet;
...
@WebServlet("/acl")
public class MyAclServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
MyAclSampleService service = this.findServiceBean(req);
Foo foo = new Foo(44L);
try {
System.out.println("service.read()");
service.read(foo);
System.out.println("service.write()");
service.write(foo);
} catch (AccessDeniedException e) {
System.out.println(e.getMessage());
}
}
...
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
...>
...
<bean id="permissionGrantingStrategy" class="org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy">
<constructor-arg>
<bean class="org.springframework.security.acls.domain.ConsoleAuditLogger" />
</constructor-arg>
</bean>
...
<sec:authentication-manager>
<sec:authentication-provider>
<sec:user-service>
<sec:user name="foo" password="foo" authorities="READONLY" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
</beans>
Melden Sie sich als foo
Benutzer an und greifen Sie / acl
zu
Ausgabe der Serverkonsole
service.read()
GRANTED due to ACE: AccessControlEntryImpl[id: 10; granting: true; sid: GrantedAuthoritySid[READONLY]; permission: BasePermission[...............................R=1]; auditSuccess: true; auditFailure: false]
Foo{id=44}
service.write()
DENIED due to ACE: AccessControlEntryImpl[id: 11; granting: false; sid: GrantedAuthoritySid[READONLY]; permission: BasePermission[..............................W.=2]; auditSuccess: false; auditFailure: true]
Access is denied
insert_acl_tables.sql
INSERT INTO ACL_ENTRY (ID, ACL_OBJECT_IDENTITY, ACE_ORDER, SID, MASK, GRANTING, AUDIT_SUCCESS, AUDIT_FAILURE)
VALUES (10, 999, 0, 98, 1, true, true, false);
INSERT INTO ACL_ENTRY (ID, ACL_OBJECT_IDENTITY, ACE_ORDER, SID, MASK, GRANTING, AUDIT_SUCCESS, AUDIT_FAILURE)
VALUES (11, 999, 1, 98, 2, false, false, true);
applicationContext.xml
<bean id="permissionGrantingStrategy" class="org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy">
<constructor-arg>
<bean class="org.springframework.security.acls.domain.ConsoleAuditLogger" />
</constructor-arg>
</bean>
AuditLogger
ist auf DefaultPermissionGrantingStrategy
gesetztDie Implementierung von ConsoleAuditLogger
sieht folgendermaßen aus:
ConsoleAuditLogger.java
package org.springframework.security.acls.domain;
import org.springframework.security.acls.model.AccessControlEntry;
import org.springframework.security.acls.model.AuditableAccessControlEntry;
import org.springframework.util.Assert;
public class ConsoleAuditLogger implements AuditLogger {
public void logIfNeeded(boolean granted, AccessControlEntry ace) {
Assert.notNull(ace, "AccessControlEntry required");
if (ace instanceof AuditableAccessControlEntry) {
AuditableAccessControlEntry auditableAce = (AuditableAccessControlEntry) ace;
if (granted && auditableAce.isAuditSuccess()) {
System.out.println("GRANTED due to ACE: " + ace);
}
else if (!granted && auditableAce.isAuditFailure()) {
System.out.println("DENIED due to ACE: " + ace);
}
}
}
}
import org.springframework.security.acls.model.AuditableAcl;
...
ObjectIdentityImpl objectIdentity = new ObjectIdentityImpl(Foo.class, 44L);
AuditableAcl acl = (AuditableAcl) this.aclService.readAclById(objectIdentity);
acl.updateAuditing(0, true, false);
this.aclService.updateAcl(acl);
Standardmäßig sind nur fünf Berechtigungen verfügbar: "Lesen", "Schreiben", "Erstellen", "Löschen" und "Verwaltung". Sie können jedoch zusätzliche eigene Berechtigungen definieren.
Versuchen Sie, "32" ("100000" in binärer Notation) zu machen.
MyPermission.java
package sample.spring.security.acl;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.model.Permission;
public class MyPermission extends BasePermission {
public static final Permission HOGE = new MyPermission(0b100000, 'H');
private MyPermission(int mask, char code) {
super(mask, code);
}
}
--Erstellen Sie Ihre eigene Berechtigungsklasse, indem Sie BasePermission erben --Erstellen Sie eine Konstante namens "HOGE", setzen Sie die Maske auf "0b100000" ("32" in Dezimalzahl) und setzen Sie den Code auf "H", um die Instanz festzulegen.
insert_acl_tables.sql
INSERT INTO ACL_CLASS (ID, CLASS)
VALUES (100, 'sample.spring.security.domain.Foo');
INSERT INTO ACL_SID (ID, PRINCIPAL, SID)
VALUES (9, true, 'hoge');
INSERT INTO ACL_SID (ID, PRINCIPAL, SID)
VALUES (98, false, 'READONLY');
INSERT INTO ACL_SID (ID, PRINCIPAL, SID)
VALUES (99, false, 'HOGE');
INSERT INTO ACL_OBJECT_IDENTITY (ID, OBJECT_ID_CLASS, OBJECT_ID_IDENTITY, PARENT_OBJECT, OWNER_SID, ENTRIES_INHERITING)
VALUES (999, 100, 44, NULL, 9, false);
INSERT INTO ACL_ENTRY (ID, ACL_OBJECT_IDENTITY, ACE_ORDER, SID, MASK, GRANTING, AUDIT_SUCCESS, AUDIT_FAILURE)
VALUES (10, 999, 0, 98, 1, true, false, false);
INSERT INTO ACL_ENTRY (ID, ACL_OBJECT_IDENTITY, ACE_ORDER, SID, MASK, GRANTING, AUDIT_SUCCESS, AUDIT_FAILURE)
VALUES (11, 999, 1, 99, 32, true, false, false);
--Grant read
Erlaubnis zur READONLY
Autorität
--Grant 32
( HOGE
definiert in MyPermission
) Erlaubnis zur HOGE
Autorität
MyAclSampleService.java
package sample.spring.security.service;
import org.springframework.security.access.prepost.PreAuthorize;
import sample.spring.security.domain.Foo;
public class MyAclSampleService {
@PreAuthorize("hasPermission(#foo, read)")
public void read(Foo foo) {
System.out.println(foo);
}
@PreAuthorize("hasPermission(#foo, 'hoge')")
public void hoge(Foo foo) {
System.out.println(foo);
}
}
--Überprüfen Sie die Berechtigungen mit "Lesen" bzw. "Hoge"
MyAclServlet.java
package sample.spring.security.servlet;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import sample.spring.security.domain.Foo;
import sample.spring.security.service.MyAclSampleService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@WebServlet("/acl")
public class MyAclServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
MyAclSampleService service = this.findServiceBean(req);
Foo foo = new Foo(44L);
this.callMethod("read", () -> service.read(foo));
this.callMethod("hoge", () -> service.hoge(foo));
}
private void callMethod(String method, Runnable runnable) {
try {
System.out.println(method);
runnable.run();
} catch (AccessDeniedException e) {
System.out.println(e.getMessage());
}
}
...
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
...>
...
<bean id="permissionFactory" class="org.springframework.security.acls.domain.DefaultPermissionFactory">
<constructor-arg value="sample.spring.security.acl.MyPermission" />
</bean>
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator">
<bean class="org.springframework.security.acls.AclPermissionEvaluator">
<constructor-arg ref="aclService" />
<property name="permissionFactory" ref="permissionFactory" /> ★
</bean>
</property>
</bean>
<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
<constructor-arg ref="dataSource" />
<constructor-arg ref="aclCache" />
<constructor-arg ref="aclAuthorizationStrategy" />
<constructor-arg ref="permissionGrantingStrategy" />
<property name="permissionFactory" ref="permissionFactory" /> ★
</bean>
...
<sec:authentication-manager>
<sec:authentication-provider>
<sec:user-service>
<sec:user name="foo" password="foo" authorities="READONLY" />
<sec:user name="bar" password="bar" authorities="HOGE" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
</beans>
Class
-Objekt Ihrer eigenenPermission
( MyPermission
) anMelden Sie sich als foo
Benutzer an und greifen Sie / acl
zu
Konsolenausgabe
read
Foo{id=44}
hoge
Access is denied
Melden Sie sich als bar
Benutzer an und greifen Sie / acl
zu
Konsolenausgabe
read
Access is denied
hoge
Foo{id=44}
MyPermission.java
package sample.spring.security.acl;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.model.Permission;
public class MyPermission extends BasePermission {
public static final Permission HOGE = new MyPermission(0b100000, 'H');
private MyPermission(int mask, char code) {
super(mask, code);
}
}
applicationContext.xml
<bean id="permissionFactory" class="org.springframework.security.acls.domain.DefaultPermissionFactory">
<constructor-arg value="sample.spring.security.acl.MyPermission" />
</bean>
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator">
<bean class="org.springframework.security.acls.AclPermissionEvaluator">
<constructor-arg ref="aclService" />
<property name="permissionFactory" ref="permissionFactory" />
</bean>
</property>
</bean>
<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
<constructor-arg ref="dataSource" />
<constructor-arg ref="aclCache" />
<constructor-arg ref="aclAuthorizationStrategy" />
<constructor-arg ref="permissionGrantingStrategy" />
<property name="permissionFactory" ref="permissionFactory" />
</bean>
Class
-Objekt der Berechtigungsklasse an, die Sie im Konstruktorargument dieser Klasse verwenden möchtenMyAclSampleService.java
@PreAuthorize("hasPermission(#foo, 'hoge')")
public void hoge(Foo foo) {
System.out.println(foo);
}
'
) setzen und als Zeichenfolge angeben.
--Wenn der in der Berechtigungsklasse definierte Konstantenname nur in Großbuchstaben geschrieben ist, gibt es kein Problem, da die Groß- und Kleinschreibung nicht wirklich berücksichtigt wird.
――Was dies bedeutet, dass die Prüfung in Wirklichkeit in ihrer ursprünglichen Form ("hoge") durchgeführt wird und wenn nicht, in Großbuchstaben ("HOGE").Recommended Posts