Update docs and polish

- Modify docs and add a better content.
- Add access to payload in EventSecurityExpressionRoot
  #114.
This commit is contained in:
Janne Valkealahti
2016-01-09 09:24:52 +00:00
parent e08edf0265
commit 51bc34b897
4 changed files with 141 additions and 25 deletions

View File

@@ -11,6 +11,7 @@
:core-jdbc-JdbcTemplate: http://docs.spring.io/spring/docs/{spring-version}/spring-framework-reference/html/jdbc.html#jdbc-JdbcTemplate
:sm-statecontext: http://docs.spring.io/spring-statemachine/docs/{spring-statemachine-version}/api/org/springframework/statemachine/StateContext.html
:sm-statecontext-stage: http://docs.spring.io/spring-statemachine/docs/{spring-statemachine-version}/api/org/springframework/statemachine/StateContext.Stage.html
:spring-security-site: http://projects.spring.io/spring-security
= Spring Statemachine - Reference Documentation

View File

@@ -1076,10 +1076,10 @@ More about error handling shown in above example, see section
[[sm-security]]
== State Machine Security
Security features are build atop of functionality from a _Spring
Security_. Security features are handy when it is required to protect
part of a state machine execution and interaction with it. More
detailed info can be found from section <<sm-security-details>>.
Security features are build atop of functionality from a
{spring-security-site}[_Spring Security_]. Security features are
handy when it is required to protect part of a state machine
execution and interaction with it.
[IMPORTANT]
====
@@ -1088,13 +1088,26 @@ we don't go into details of how overall security framework works. For
this read _Spring Security_ reference documentation.
====
First level of defence with a security is naturally protecting events
which really are a driver from user point of view what is going to
happen in a state machine. More fine grained security settings can
then be defined for transitions and actions. This can be think of like
allowing an employee to access a building, walk around it and then
giving more detailed access rights to enter different rooms and allow
to switch lights on and off while being on those rooms. If you trust
your users then event security may be all you need, if you don't, then
more detailed security needs to be applied.
More detailed info can be
found from section <<sm-security-details>>.
[TIP]
====
For complete example, see sample <<statemachine-examples-security>>.
====
=== Configuring Security
All generic configurations for security are done from
All generic configurations for security are done in
`SecurityConfigurer` which is obtained from
`StateMachineConfigurationConfigurer`. Security is disabled on
default even if _Spring Security_ classes are
@@ -1172,38 +1185,125 @@ Attributes are easier to use but are relatively limited in terms of
functionality. Expressions provide more features but are a little bit
of harder to use.
This section is splitted into different subsections because we're
re-using something from a _Spring Security_ and then do custom
attributes and expression handling for events and transitions.
==== Generic Attribute Usage
On default `AccessDecisionManager` instances for events and
transitions use a `RoleVoter`, meaning you can use role attributes.
transitions both use a `RoleVoter`, meaning you can use role attributes
familiar from _Spring Security_.
For attributes we have 3 different comparison types, `ANY`, `ALL` and
`MAJORITY` which maps into voters `AffirmativeBased`, `UnanimousBased`
and `ConsensusBased` respectively.
`MAJORITY` which maps into default access decision managers
`AffirmativeBased`, `UnanimousBased` and `ConsensusBased` respectively.
If custom `AccessDecisionManager` has been defined, comparison type is
effectively discarded as it's only used to create a default manager.
==== Generic Expression Usage
Security expressions needs to return either _TRUE_ or _FALSE_.
The base class for expression root objects is
`SecurityExpressionRoot`. This provides some common expressions which
are available in both transition and event security.
[[common-expressions]]
.Common built-in expressions
|===
| Expression | Description
| `hasRole([role])`
| Returns `true` if the current principal has the specified role. By
default if the supplied role does not start with 'ROLE_' it will be
added. This can be customized by modifying the `defaultRolePrefix` on
`DefaultWebSecurityExpressionHandler`.
| `hasAnyRole([role1,role2])`
| Returns `true` if the current principal has any of the supplied
roles (given as a comma-separated list of strings). By default if the
supplied role does not start with 'ROLE_' it will be added. This can
be customized by modifying the `defaultRolePrefix` on
`DefaultWebSecurityExpressionHandler`.
| `hasAuthority([authority])`
| Returns `true` if the current principal has the specified authority.
| `hasAnyAuthority([authority1,authority2])`
| Returns `true` if the current principal has any of the supplied
roles (given as a comma-separated list of strings)
| `principal`
| Allows direct access to the principal object representing the
current user
| `authentication`
| Allows direct access to the current `Authentication` object obtained
from the `SecurityContext`
| `permitAll`
| Always evaluates to `true`
| `denyAll`
| Always evaluates to `false`
| `isAnonymous()`
| Returns `true` if the current principal is an anonymous user
| `isRememberMe()`
| Returns `true` if the current principal is a remember-me user
| `isAuthenticated()`
| Returns `true` if the user is not anonymous
| `isFullyAuthenticated()`
| Returns `true` if the user is not an anonymous or a remember-me user
| `hasPermission(Object target, Object permission)`
| Returns `true` if the user has access to the provided target for the
given permission. For example, `hasPermission(domainObject, 'read')`
| `hasPermission(Object targetId, String targetType, Object
permission)`
| Returns `true` if the user has access to the provided target for the
given permission. For example, `hasPermission(1,
'com.example.domain.Message', 'read')`
|===
==== Event Attributes
Event id can be matched by using prefix _EVENT__. For example matching
event `A` would match with attribte _EVENT_A_.
Event id can be matched by using prefix `EVENT_`. For example matching
event `A` would match with attribte `EVENT_A`.
==== Event Expressions
For generic options for expressions, see _Spring Security_ docs. We
inherit from `SecurityExpressionRoot` and options from there are
available.
The base class for expression root object for event is
`EventSecurityExpressionRoot`. This provides access to a `Message`
object which is passed around with eventing.
.Event expressions
|===
| Expression | Description
| `hasEvent(Object event)`
| Returns `true` if the event matches given event.
|===
==== Transition Attributes
Matching transition sources and targets, use prefixes
_TRANSITION_SOURCE__ and _TRANSITION_TARGET__ respectively.
`TRANSITION_SOURCE_` and `TRANSITION_TARGET_` respectively.
==== Transition Expressions
For generic options for expressions, see _Spring Security_ docs. We
inherit from `SecurityExpressionRoot` and options from there are
available.
The base class for expression root object for transition is
`TransitionSecurityExpressionRoot`. This provides access to a
`Transition`
object which is passed around for transition changes.
.Transition expressions
|===
| Expression | Description
| `hasSource(Object source)`
| Returns `true` if the transition source matches given source.
| `hasTarget(Object target)`
| Returns `true` if the transition target matches given target.
|===
[[sm-security-details]]
=== Understanding Security
@@ -1212,14 +1312,17 @@ state machine. Not really something you'd need to know but it is
always better to be transparent instead of hiding all the magic what
happens behind a scenes.
[NOTE]
====
Security only makes sense if _State Machine_ is executed in a wallet
garden where user don't have direct access to the application thus
could modify Spring Security's `SecurityContext` hold in a thread
local. If user controls the jvm, then effectively there is no security
at all.
====
Integration point for security is done with a
`StateMachineInterceptor` which is then added automatically into a
<<sm-interceptor,_StateMachineInterceptor_>> which is then added automatically into a
state machine if security is enabled. Specific class is a
`StateMachineSecurityInterceptor` which intercepts events and
transitions. This interceptor then consults Spring Security's

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.springframework.statemachine.security;
import org.springframework.messaging.Message;
import org.springframework.security.access.expression.SecurityExpressionRoot;
import org.springframework.security.core.Authentication;
import org.springframework.util.ObjectUtils;
/**
* The {@link SecurityExpressionRoot} used for {@link Message} expressions.
@@ -29,8 +30,19 @@ public class EventSecurityExpressionRoot extends SecurityExpressionRoot {
public final Message<?> message;
/**
* Instantiates a new event security expression root.
*
* @param authentication the authentication
* @param message the message
*/
public EventSecurityExpressionRoot(Authentication authentication, Message<?> message) {
super(authentication);
this.message = message;
}
public final boolean hasEvent(Object source) {
return ObjectUtils.nullSafeEquals(source, message.getPayload());
}
}

View File

@@ -45,8 +45,8 @@ public class TransitionSecurityExpressionRoot extends SecurityExpressionRoot {
return ObjectUtils.nullSafeEquals(source, transition.getSource().getId());
}
public final boolean hasTarget(Object source) {
return ObjectUtils.nullSafeEquals(source, transition.getTarget().getId());
public final boolean hasTarget(Object target) {
return ObjectUtils.nullSafeEquals(target, transition.getTarget().getId());
}
}