Spring Security (6.2.x) Custom Usage#
- AuthenticationProvider
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class AkSkAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
// 进行实际的用户信息校验
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
System.out.println(authentication.getName());
List<String> perms = new ArrayList<>(3);
perms.add("operator");
perms.add("viewer");
perms.add("admin");
List<SimpleGrantedAuthority> authorities = new ArrayList<>(perms.size());
for (String perm:perms) {
authorities.add(new SimpleGrantedAuthority(perm));
}
return new MyToken("ak","sk",authorities);
}
// 判断当前Authentication 是否会用该Provider校验
@Override
public boolean supports(Class<?> authentication) {
return MyToken.class.isAssignableFrom(authentication);
}
}
java- AbstractAuthenticationProcessingFilter
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class AkSkAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public AkSkAuthenticationFilter(String defaultFilterProcessesUrl, AuthenticationManager authenticationManager) {
super(new AntPathRequestMatcher(defaultFilterProcessesUrl, "GET"));
this.setAuthenticationManager(authenticationManager);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
String ak = request.getHeader("ak");
String sk = request.getHeader("sk");
if ("ak".equals(ak) && "sk".equals(sk)) {
List<String> perms = new ArrayList<>(3);
perms.add("operator");
perms.add("viewer");
perms.add("admin");
List<SimpleGrantedAuthority> authorities = new ArrayList<>(perms.size());
for (String perm:perms) {
authorities.add(new SimpleGrantedAuthority(perm));
}
// 调用Provider校验
return this.getAuthenticationManager().authenticate(new MyToken(ak,sk,authorities));
}
return null;
}
// 成功
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
System.out.println("success");
final String xId = UUID.randomUUID().toString();
response.getWriter().write(xId);
}
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
AuthenticationException failed)
throws IOException, ServletException {
System.out.println("fail");
super.unsuccessfulAuthentication(request, response, failed);
}
}
java- Configuration
import com.example.demo.sec.AkSkFilter;
import com.example.demo.sec.AkSkAuthenticationProvider;
import com.example.demo.sec.AkSkAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.csrf.CsrfFilter;
import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration {
@Autowired
private AkSkFilter akSkFilter;
// AbstractAuthenticationProcessingFilter
@Bean
public AkSkAuthenticationFilter theAuthFilter() {
return new AkSkAuthenticationFilter("/v1/token",authenticationManager());
}
// 包装 AuthenticationProvider
@Bean
public AuthenticationManager authenticationManager(){
ProviderManager authenticationManager = new ProviderManager(authenticationProvider());
authenticationManager.setEraseCredentialsAfterAuthentication(true);
return authenticationManager;
}
// AuthenticationProvider
@Bean
public AuthenticationProvider authenticationProvider() {
return new AkSkAuthenticationProvider();
}
@Bean
public SecurityFilterChain authorizeRequestsFilterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(req ->
req.requestMatchers("/v1/token")
.permitAll()
.anyRequest().authenticated()
)
// 设置authenticationManager
.authenticationManager(authenticationManager())
.sessionManagement(session -> session.sessionCreationPolicy(STATELESS))
// 设置自定义的校验
.addFilterAfter(theAuthFilter(), CsrfFilter.class)
.addFilterBefore(akSkFilter, AkSkAuthenticationFilter.class);
return http.build();
}
javaSpring IoC and Bean#
The org.springframework.beans and org.springframework.context packages are the basis for Spring Framework’s IoC container. ↗ The BeanFactory interface provides an advanced configuration mechanism capable of managing any type of object. ApplicationContext is a sub-interface of BeanFactory. It adds:
- Easier integration with Spring’s AOP features
- Message resource handling (for use in internationalization)
- Event publication
- Application-layer specific contexts such as the WebApplicationContext for use in web applications.

Create Config Get Beans#
ApplicationContext context1 = new ClassPathXmlApplicationContex("services.xml");
ApplicationContext context2 = new GenericGroovyApplicationContext("services.groovy");
ApplicationContext context3 = FileSystemXmlApplicationContext("")javaApplicationContext context = new ClassPathXmlApplicationContext("services.xml");
// getBean
DemoEntity entity1 = context.getBean("entity1", DemoEntity.class);
System.out.println(entity1);
DemoEntity entityAlias = context.getBean("entityAlias",DemoEntity.class);
System.out.println(entityAlias);
assert entity1 == entityAlias;
javaXML config attrs#
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- factory-method -> public static factory method -->
<bean id="entity2" class="tech.realcpf.spring.dto.DemoEntity" factory-method="createInstance">
<property name="name" value="jiacheng.liu"/>
<property name="age" value="25"/>
</bean>
<!-- use xmlns:p="http://www.springframework.org/schema/p"-->
<bean id="entity3" class="tech.realcpf.spring.dto.DemoEntity"
destroy-method="destroy"
p:name="jc.liu"
p:age="89">
<!-- additional collaborators and configuration for this bean go here -->
</bean>
<!-- constructor-arg -->
<bean id="entity1" class="tech.realcpf.spring.dto.DemoEntity">
<constructor-arg type="java.lang.String" value="by constructor" name="name" index="0"></constructor-arg>
<constructor-arg type="java.lang.Integer" value="123" name="age" index="1"></constructor-arg>
</bean>
<alias name="entity1" alias="entityAlias"></alias>
<!-- depends-on other beans -->
<bean id="beanOne" class="ExampleBean" depends-on="manager"/>
<!-- <bean id="manager" class="ManagerBean" />-->
<!-- lazy-init -->
<bean id="lazy" class="com.something.ExpensiveToCreateBean" lazy-init="true"/>
<!-- <bean name="not.lazy" class="com.something.AnotherBean"/>-->
<!-- init method -->
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
<!-- scope -->
<bean id="exampleInitBean" class="examples.ExampleBean" scope="prototype"/>
</beans>xml

BeanPostProcessor#
private static final BeanPostProcessor beanPostProcessor = new BeanPostProcessor() {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Bean '" + beanName + "' created : " + bean.toString());
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
};
// PropertyOverrideConfigurer
// PropertySourcesPlaceholderConfigurer
private static final BeanFactoryPostProcessor beanFactoryPostProcessor = new BeanFactoryPostProcessor() {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
};
javaSpring SPI#
通过 resources/META-INF/spring.factories 作为SPI的配置文件
内容如下:
org.springframework.context.ApplicationContextInitializer=\
tech.realcpf.spring.DemoApplicationContextInitializer
org.springframework.context.ApplicationListener=\
tech.realcpf.spring.DemoApplicationListener
如果用spring-boot,再spring-boot3之后配置文件改成
resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 作为SPI的配置文件
内容则是一个类一行
其中 org.springframework.boot.autoconfigure.AutoConfiguration 是Interface名
plaintextSpring Aop#
https://docs.spring.io/spring-framework/reference/core/aop-api/pointcuts.html ↗
Proxy - ProxyFactoryBean#
ApplicationContext context =
new ClassPathXmlApplicationContext("aopdemo.xml");
IDemoModel model = (IDemoModel) context.getBean("demoModelProxy");
System.out.println(model.hello("jc.liu"));java
<bean id="demoModelProxy"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>tech.realcpf.spring.aop.IDemoModel</value>
</list>
</property>
<property name="target" ref="demoModelImpl">
</property>
<property name="interceptorNames">
<list>
<value>demoModelArgs</value> <!-- impl MethodBeforeAdvice -->
<value>demoModelReturn</value> <!-- impl AfterReturningAdvice -->
</list>
</property>
</bean>
xmlAuto Proxy - BeanNameAutoProxyCreator#
ApplicationContext context =
new ClassPathXmlApplicationContext("aopdemo.xml");
IDemoModel demoModel = context.getBean(IDemoModel.class);
System.out.println(demoModel.hello("jc.liu"));
java
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<value>demoModelArgs</value>
<value>demoModelReturn</value>
</list>
</property>
<!-- for auto match-->
<property name="beanNames" value="*Model"></property>
</bean>
xmlAspectj#
// call before
@Before("tech.realcpf.spring.aop.aj.SystemArchitecture.service()")
public void callBefore(JoinPoint joinPoint) {
System.out.println("Before : " + Arrays.toString(joinPoint.getArgs()));
}
// call after
@AfterReturning(pointcut = "tech.realcpf.spring.aop.aj.SystemArchitecture.service()",
returning = "result")
public void logResult(Object result) {
System.out.println("after :" + result);
}
@Pointcut("execution(* tech.realcpf.spring.aop.aj..*(..))")
public void service() {}
java
<!-- enable aspectj -->
<aop:aspectj-autoproxy/>
xml#Spring EL#
https://docs.spring.io/spring-framework/reference/core/expressions/evaluation.html ↗
更多的语法语义 ↗#
static class Simple {
public List<Boolean> booleans = new ArrayList<>();
}
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello World'.concat('!')");
String message = (String) exp.getValue();
System.out.println(message);
System.out.println(
parser.parseExpression("'hello'.bytes.length").getValue()
);
Simple simple = new Simple();
simple.booleans.add(false);
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
parser.parseExpression("booleans[0]")
.setValue(context,simple,"true");
assert simple.booleans.get(0);
java