0

I'm using Spring Boot 2.2.5.RELEASE. In my application.properties file I have the following properties:

security.basic.authorize-mode=authenticated
security.basic.enabled=true

Since they're no longer customizable because of simplification of Spring Boot default security configuration,

enter image description here

I can't use it via application.properties.

I've researched and tried solution using annotation @ConditionalOnExpression for two properties like:

@ConditionalOnExpression("${security.basic.enabled:true} && ${security.basic.authorize-mode:authenticated}")

And by the same logic was this one. But it doesn't work for me, because I have authenticated instead of values true/false:

enter image description here

So, I've tried to write like:

@ConditionalOnExpression("${security.basic.enabled:true} && ${security.basic.authorize.mode}.equals('authenticated')")

it compiles good, but after running the program, I'm getting the error:

Caused by: org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: 'lcurly({)'
    at org.springframework.context.expression.StandardBeanExpressionResolver.evaluate(StandardBeanExpressionResolver.java:164) ~[spring-context-5.2.4.RELEASE.jar:5.2.4.RELEASE]
    at org.springframework.boot.autoconfigure.condition.OnExpressionCondition.evaluateExpression(OnExpressionCondition.java:60) ~[spring-boot-autoconfigure-2.2.5.RELEASE.jar:2.2.5.RELEASE]
    at org.springframework.boot.autoconfigure.condition.OnExpressionCondition.getMatchOutcome(OnExpressionCondition.java:48) ~[spring-boot-autoconfigure-2.2.5.RELEASE.jar:2.2.5.RELEASE]
    at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47) ~[spring-boot-autoconfigure-2.2.5.RELEASE.jar:2.2.5.RELEASE]
    ... 26 common frames omitted
Caused by: org.springframework.expression.spel.SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: 'lcurly({)'
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.doParseExpression(InternalSpelExpressionParser.java:135) ~[spring-expression-5.2.4.RELEASE.jar:5.2.4.RELEASE]
    at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:61) ~[spring-expression-5.2.4.RELEASE.jar:5.2.4.RELEASE]
    at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:33) ~[spring-expression-5.2.4.RELEASE.jar:5.2.4.RELEASE]

Can I use @ConditionalOnExpression or @ConditionalOnProperty for multiple properties, but not only for boolean true/false values?

UPD: I've added single quotes:

@ConditionalOnExpression("${security.basic.authorize.mode:'authenticated'} && ${security.basic.enabled:true}")

enter image description here

In this case I'm getting:

Caused by: org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.lang.Boolean] for value 'authenticated'; nested exception is java.lang.IllegalArgumentException: Invalid boolean value 'authenticated'
    at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:47) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:191) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
    at org.springframework.expression.spel.support.StandardTypeConverter.convertValue(StandardTypeConverter.java:70) ~[spring-expression-5.2.4.RELEASE.jar:5.2.4.RELEASE]
    ... 36 common frames omitted
Caused by: java.lang.IllegalArgumentException: Invalid boolean value 'authenticated'
    at org.springframework.core.convert.support.StringToBooleanConverter.convert(StringToBooleanConverter.java:63) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
    at org.springframework.core.convert.support.StringToBooleanConverter.convert(StringToBooleanConverter.java:31) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
    at org.springframework.core.convert.support.GenericConversionService$ConverterAdapter.convert(GenericConversionService.java:385) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
    at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
    ... 38 common frames omitted

And also I tried using environment.getProperty() for @ConditionalOnExpression annotation:

@ConditionalOnExpression("#{environment.getProperty('security.basic.authorize.mode') eq('authenticated') && environment.getProperty('security.basic.enabled') eq('true')}")
invzbl3
  • 5,872
  • 9
  • 36
  • 76
  • You don't have an expressin, just 2 value expressions with a default... – M. Deinum Mar 24 '20 at 13:43
  • so, can I use these two via specific annotation instead of `application.properties`? – invzbl3 Mar 24 '20 at 13:59
  • Do I need to use [@Value](https://www.baeldung.com/spring-value-defaults) annotation instead of `@ConditionalOnExpression` & `@ConditionalOnProperty`? Looks like I've found [similar issue](https://stackoverflow.com/q/49714249/8370915), but with `true/false`. – invzbl3 Mar 24 '20 at 14:46
  • BUt why do you want to use properties that are no longer supported? If you want security add the websecurityconfigurer else leave it out. – M. Deinum Mar 25 '20 at 06:28
  • Because I've upgraded version of Spring Boot, so these properties must be removed from `application.properties` in favor of `websecurityconfigurer` [custom settings](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Security-2.0). I'm not very sure that I understand how to do the same programmatically. Can you show me an example how to use it for my properties? – invzbl3 Mar 25 '20 at 15:40
  • 1
    Ditch the properties and just include a security configuration with a rule to only allow authenticated access. – M. Deinum Mar 25 '20 at 15:42
  • Thanks, I've modified a bit own answer according to your hint – invzbl3 Mar 25 '20 at 21:59

1 Answers1

0

As mentioned by @M. Deinum, I can use WebSecurityConfigurerAdapter with rules for authenticated access:

public class SpringSecurityConfiguration
        extends WebSecurityConfigurerAdapter {
    private final UserInfoDetailsService userInfoDetailsService;

    public SpringSecurityConfiguration_Database(UserInfoDetailsService userInfoDetailsService) {
        this.userInfoDetailsService = userInfoDetailsService;
    }

    @Override
    protected void configure(
            AuthenticationManagerBuilder authenticationManagerBuilder)
            throws Exception {
        authenticationManagerBuilder
                .userDetailsService(userInfoDetailsService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/api/user/**", "/h2-console")
                .authenticated()
                .and()
                .httpBasic()
                .realmName("...")
                .and()
                .csrf()
                .disable();
    }
}
invzbl3
  • 5,872
  • 9
  • 36
  • 76
  • 1
    Not instead, as you will still need this configuration class. WIth just the properties it won't work, you can only control if this configuration is applied or not. But if the properties never change (between your diferrent profiles) trying to add them will only add complexity and nothing functional. – M. Deinum Mar 26 '20 at 06:55