Не могу понять как это вообще работает. Использую ThreadLocal<>. Простой пример:
Secure Bean
public class SecureBean {
public void writeSecureMessage() {
System.out.println("Test");
}
}
UserInfo.java
public class UserInfo {
private String name;
private String password;
/* Геттеры и сеттеры */
}
SimpleSecurityManager
public class SimpleSecurityManager implements SecurityManager {
private static ThreadLocal<UserInfo> threadLocal = new ThreadLocal<>();
public void login(String userName, String userPassword) {
threadLocal.set(new UserInfo(userName, userPassword));
}
public void logout() {
threadLocal.set(null);
}
public UserInfo getLoggedOnUser() {
return threadLocal.get();
}
}
SecurityAdvise.java
public class SecurityAdvise implements MethodBeforeAdvice {
private SecurityManager securityManager;
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
UserInfo user = securityManager.getLoggedOnUser();
if (user == null) {
System.out.println("No user auth");
throw new SecurityException(
"You must be logged to attempt to invoke this method: " + method.getName()
);
} else if ("admin".equals(user.getName())) {
System.out.println("Logged user is admin - OK!");
} else {
System.out.println("Bad user!");
throw new SecurityException(
"You must be logged to attempt to invoke this method: " + method.getName()
);
}
}
public void setSecurityManager(SecurityManager securityManager) {
this.securityManager = securityManager;
}
}
AppConfig.java
@Configuration
public class AppConfig {
@Bean("securityManager")
public SecurityManager securityManager() {
return new SimpleSecurityManager();
}
@Bean("securityAdvise")
public SecurityAdvise securityAdvise() {
SecurityAdvise advise = new SecurityAdvise();
advise.setSecurityManager(securityManager());
return advise;
}
@Bean("secureBean")
public SecureBean secureBean() {
SecureBean target = new SecureBean();
SecurityAdvise advise = securityAdvise();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvice(advise);
return (SecureBean) proxyFactory.getProxy();
}
}
Application.java(Работает)
public class Application {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
SecureBean secureBean = (SecureBean) context.getBean("secureBean");
SecurityManager securityManager = (SecurityManager) context.getBean("securityManager");
securityManager.login("admin", "pass");
secureBean.writeSecureMessage();
securityManager.logout();
}
}
Application.java(Всё так же работает)
public class Application {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
SecureBean secureBean = (SecureBean) context.getBean("secureBean");
SecurityManager securityManager = (SecurityManager) context.getBean("securityManager");
securityManager.login("admin", "pass");
new ThreadLocal<UserInfo>().set(new UserInfo("Wrong username", "Another thread?"));
secureBean.writeSecureMessage();
securityManager.logout();
}
}
Application.java(Опять же работает)
public class Application {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
SecureBean secureBean = (SecureBean) context.getBean("secureBean");
SecurityManager securityManager = new SecurityManager();
securityManager.login("admin", "pass");
secureBean.writeSecureMessage();
securityManager.logout();
}
}
Определение ThreadLocal:
Этот класс предоставляет локальные переменные потока. Эти переменные
отличаются от их обычных аналогов тем, что каждый поток, который
обращается к нему (посредством метода get или set), имеет свою
собственную, независимо инициализированную копию переменной.
Экземпляры ThreadLocal обычно представляют собой частные статические
поля в классах, которые хотят связать состояние с потоком (например,
идентификатор пользователя или идентификатор транзакции).
По вашему коду видно, что вы можете вызывать метод writeSecureMessage() если имя пользователя admin.
ThreadLocal здесь используется, чтобы нельзя это было делать из другого потока. То есть, если вы создаете новый поток, то вам опять надо делать login("admin",).
Сборка персонального компьютера от Artline: умный выбор для современных пользователей