I need to remove the soapAction from this header:
Headers: {Accept=[*/*], SOAPAction ["http://www.ya.ru/mybank/method/getDollars"]}
My configuration looks like this:
#PostConstruct
public void initialization(){
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(MyClass.class);
factory.setAddress(myWsdlUrl);
service = (MyClass) factory.create();
Client client = ClientProxy.getClient(service);
}
#Bean
public SAAJMetaFactory messageFactory(){
return new SAAJMetaFactoryImpl();
}
In the class of service I make such a request:
#Service
public class MyIntegrationImpl implements MyIntegration {
private MyClass service;
public MyIntegrationImpl(MyClass service) {
this.service = service;
}
#Override
public Info getVpc(ReqClass req, String clientPhone) {
return service.getInfo(req, clientPhone);
}
}
I found this code, but I do not know how to apply it:
public class RemoveActionHandler implements SOAPHandler<SOAPMessageContext> {
#Override
public Set<QName> getHeaders() {
System.out.println("Server : getHeaders()");
return null;
}
#Override
public boolean handleMessage(SOAPMessageContext context) {
if ("".equals(context.get(BindingProvider.SOAPACTION_URI_PROPERTY)))
context.put(BindingProvider.SOAPACTION_URI_PROPERTY, null);
return true;
}
#Override
public boolean handleFault(SOAPMessageContext context) {
System.out.println("Server : handleFault()");
return true;
}
#Override
public void close(MessageContext context) {
System.out.println("Server : close()");
}
}
This code can remove the required header
It was necessary to create an interceptor:
public class ServiceMyInterceptor extends AbstractSoapInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(ServiceMyInterceptor.class);
public ServiceMyInterceptor() {
super(Phase.USER_PROTOCOL);
addAfter(ReadHeadersInterceptor.class.getName());
addAfter(EndpointSelectionInterceptor.class.getName());
}
#Override
public void handleMessage(SoapMessage message) throws Fault {
Map<String, List<String>> headers = CastUtils.cast((Map)message.get(Message.PROTOCOL_HEADERS));
if (headers != null) {
List<String> sa = headers.get("SOAPAction");
String action = null;
if (sa != null && sa.size() > 0) {
action = sa.get(0);
}
LOGGER.info("Remove SOAPAction who equals {}", action);
headers.remove("SOAPAction");
}
}
}
And apply it this way:
#PostConstruct
public void initialization(){
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(MyClass.class);
factory.setAddress(myWsdlUrl);
service = (MyClass) factory.create();
Client client = ClientProxy.getClient(service);
ServiceMyInterceptor interceptor = new ServiceMyInterceptor();
client.getEndpoint().getOutInterceptors().add(interceptor);
}
If you judge by logs, then the SOAPAction header is gone.
Related
I am using spring gateway as the gateway of my project, now I found it did not enter the custom CustomAddRequestHeaderGatewayFilterFactory, the code about CustomAddRequestHeaderGatewayFilterFactory in my project look like this:
#Component
public class CustomAddRequestHeaderGatewayFilterFactory implements GatewayFilterFactory<CustomAddRequestHeaderGatewayFilterFactory.CustomAddRequestHeaderConfig> {
private final Class<CustomAddRequestHeaderConfig> configClass = CustomAddRequestHeaderConfig.class;
#Override
public List<String> shortcutFieldOrder() {
return new ArrayList<>(Arrays.asList("headerName", "headerValue"));
}
#Override
public GatewayFilter apply(CustomAddRequestHeaderConfig config) {
return ((exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest().mutate().headers(httpHeaders -> {
httpHeaders.set(config.getHeaderName(), config.getHeaderValue());
}).build();
return chain.filter(exchange.mutate().request(request).build());
});
}
#Override
public Class<CustomAddRequestHeaderConfig> getConfigClass() {
return configClass;
}
#Override
public CustomAddRequestHeaderConfig newConfig() {
return BeanUtils.instantiateClass(this.configClass);
}
public static class CustomAddRequestHeaderConfig {
private String headerName;
private String headerValue;
public String getHeaderName() {
return headerName;
}
public void setHeaderName(String headerName) {
this.headerName = headerName;
}
public String getHeaderValue() {
return headerValue;
}
public void setHeaderValue(String headerValue) {
this.headerValue = headerValue;
}
}
}
my configuration in application.properties look like this:
# dolphin music
spring.cloud.gateway.discovery.locator.enabled=true
spring.cloud.gateway.discovery.locator.lower-case-service-id=true
spring.cloud.gateway.routes[0].id=dolphin-music-service
# forward by ip:port way
spring.cloud.gateway.routes[0].uri=http://10.107.64.246:11014
# forward by service name way
# spring.cloud.gateway.routes[0].uri=lb://
spring.cloud.gateway.routes[0].predicates[0]=Path=/music/**
spring.cloud.gateway.routes[0].filters[0]=CustomAddRequestHeaderGatewayFilterFactory=customHeaderName,customHeaderValue
what should I do to make it enter the filter as expect? My request url look like this:
https://music-api.example.com/music/playlist/v1/playlist
I also tried the config like this:
spring.cloud.gateway.routes[0].filters[0]=CustomAddRequestHeader=customHeaderName,customHeaderValue
still did not work.
I have InheritableThreadLocal<ConcurrentHashMap<String, Object>> thread that initializes when a request comes via the filter and set some transaction_id in it.
Now at the service layer, I'm calling 10 different API calls via CompletableFuture. All API service class have one execute method that is using RestTempate to make an API call. I put #HystrixCommand on execute method.
execute method is void type but it put the API response in InheritableThreadLocal object.
Problem is when an API call fails Hystrix call FallBackMethod and when I put error response in InheritableThreadLocal, I'm not able to send that error response to the client.
ThreadLocalUtil.class
public class ThreadLocalUtil {
private static InheritableThreadLocal<ConcurrentHashMap<String, Object>> transmittableThreadLocal = new InheritableThreadLocal<>();
public static void addDataToThreadLocalMap(String key, Object value) {
Map<String, Object> existingDataMap = transmittableThreadLocal.get();
if (value != null) {
existingDataMap.put(key, value);
}
}
public static Object getDataFromThreadLocalMap(String key) {
Map<String, Object> existingDataMap = transmittableThreadLocal.get();
return existingDataMap.get(key);
}
public static void clearThreadLocalDataMap() {
if (transmittableThreadLocal != null)
transmittableThreadLocal.remove();
}
public static Object getRequestData(String key) {
Map<String, Object> existingDataMap = transmittableThreadLocal.get();
if (existingDataMap != null) {
return existingDataMap.get(key);
}
return "-1";
}
public static void initThreadLocals() {
ConcurrentHashMap<String, Object> dataForDataMap = new ConcurrentHashMap<String, Object>();
String requestId = "REQUEST_ID_" + System.currentTimeMillis();
dataForDataMap.put("REQUEST_ID", requestId);
transmittableThreadLocal.set(dataForDataMap);
}
}
CommonFilter.class
#Component
#Order(1)
public class CommonFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
ThreadLocalUtil.initThreadLocals();
filterChain.doFilter(request, response);
} catch (Exception e) {
if (e instanceof ServletException) {
throw (ServletException) e;
}
} finally {
ThreadLocalUtil.clearThreadLocalDataMap();
}
}
EmployeeService.class
#Component
public abstract class EmployeeService {
#Autowired
private ThreadLocalUtil threadLocalUtil;
public abstract void getEmployee(int employeeId);
public void fallbackMethod(int employeeid) {
threadLocalUtil.addDataToThreadLocalMap("ErrorResponse", "Fallback response:: No employee details available temporarily");
}
}
EmployeeServiceImpl.class
#Service
public class EmployeeServiceImpl extends EmployeeService {
#HystrixCommand(fallbackMethod = "fallbackMethod", commandProperties = {
#HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "900"),
#HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "10") })
public void getEmployee(int employeeId) {
System.out.println("Getting Employee details for " + employeeId + ", threadLocalUtil : " + threadLocalUtil.getDataFromThreadLocalMap("EMPLOYE_ID"));
String response = restTemplate.exchange("http://localhost:8011/findEmployeeDetails/{employeeid}",
HttpMethod.GET, null, new ParameterizedTypeReference<String>() {
}, employeeId).getBody();
threadLocalUtil.addDataToThreadLocalMap("Response", response);
}
#Autowired
RestTemplate restTemplate;
#Autowired
private ThreadLocalUtil threadLocalUtil;
}
So, first of all since internally Hystrix uses ThreadPoolExecutor (Threads created once and reused), so it is wrong to use InheritableThreadLocal.
From the above question and what you asked in my blog, I understand that you problem is
InheritableThreadLocal becomes null in hystrix fallback method
Further adding to this (you may verify this)
InheritableThreadLocal becomes null in hystrix fallback method only in case of timeouts and not in case of any other exception
I would recommend others to refer to my blog. Hystrix fallback in case of timeout, takes place in hystrix-timer thread.
Hystrix fallback execution thread
You can verify this by logging Thread.currentThread().getName()
Since the parent of hystrix-timer thread is not your calling thread, and so your transmittableThreadLocal.get() becomes null.
To solve this I would recommend using HystrixCommandExecutionHook and HystrixRequestVariableDefault. Using this you can implement hooks like onStart, onExecutionStart, onFallbackStart etc., in which you need to get/set the threadLocal variables. For more details you can refer to the last section in the blog.
Update:
For your use-case you can modify your code as follows:
ThreadLocalUtil.java
public class ThreadLocalUtil {
private static ThreadLocal<ConcurrentHashMap<String, Object>> transmittableThreadLocal = new ThreadLocal<>();
public static ConcurrentHashMap<String, Object> getThreadLocalData() {
return transmittableThreadLocal.get();
}
public static void setThreadLocalData(ConcurrentHashMap<String, Object> data) {
transmittableThreadLocal.set(data);
}
public static void addDataToThreadLocalMap(String key, Object value) {
Map<String, Object> existingDataMap = transmittableThreadLocal.get();
if (value != null) {
existingDataMap.put(key, value);
}
}
public static Object getDataFromThreadLocalMap(String key) {
Map<String, Object> existingDataMap = transmittableThreadLocal.get();
return existingDataMap.get(key);
}
public static void clearThreadLocalDataMap() {
if (transmittableThreadLocal != null)
transmittableThreadLocal.remove();
}
public static Object getRequestData(String key) {
Map<String, Object> existingDataMap = transmittableThreadLocal.get();
if (existingDataMap != null) {
return existingDataMap.get(key);
}
return "-1";
}
public static void initThreadLocals() {
transmittableThreadLocal.set(new ConcurrentHashMap<>());
String requestId = "REQUEST_ID_" + System.currentTimeMillis();
addDataToThreadLocalMap("REQUEST_ID", requestId);
}
}
EmployeeService.java
#Component
public abstract class EmployeeService {
public abstract void getEmployee(int employeeId);
public void fallbackMethod(int employeeid) {
threadLocalUtil.addDataToThreadLocalMap("ErrorResponse", "Fallback response:: No employee details available temporarily");
}
}
EmployeeServiceImpl.java
#Service
public class EmployeeServiceImpl extends EmployeeService {
#HystrixCommand(fallbackMethod = "fallbackMethod", commandProperties = {
#HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "900"),
#HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "10") })
public void getEmployee(int employeeId) {
System.out.println("Getting Employee details for " + employeeId + ", threadLocalUtil : " + threadLocalUtil.getDataFromThreadLocalMap("EMPLOYEE_ID"));
String response = restTemplate.exchange("http://localhost:8011/findEmployeeDetails/{employeeid}",
HttpMethod.GET, null, new ParameterizedTypeReference<String>() {
}, employeeId).getBody();
threadLocalUtil.addDataToThreadLocalMap("Response", response);
}
#Autowired
RestTemplate restTemplate;
}
HystrixHook.java
public class HystrixHook extends HystrixCommandExecutionHook {
private HystrixRequestVariableDefault<ConcurrentHashMap<String, Object>> hrv = new HystrixRequestVariableDefault<>();
#Override
public <T> void onStart(HystrixInvokable<T> commandInstance) {
HystrixRequestContext.initializeContext();
getThreadLocals();
}
#Override
public <T> void onExecutionStart(HystrixInvokable<T> commandInstance) {
setThreadLocals();
}
#Override
public <T> void onFallbackStart(HystrixInvokable<T> commandInstance) {
setThreadLocals();
}
#Override
public <T> void onSuccess(HystrixInvokable<T> commandInstance) {
HystrixRequestContext.getContextForCurrentThread().shutdown();
super.onSuccess(commandInstance);
}
#Override
public <T> Exception onError(HystrixInvokable<T> commandInstance, HystrixRuntimeException.FailureType failureType, Exception e) {
HystrixRequestContext.getContextForCurrentThread().shutdown();
return super.onError(commandInstance, failureType, e);
}
private void getThreadLocals() {
hrv.set(ThreadLocalUtil.getThreadLocalData());
}
private void setThreadLocals() {
ThreadLocalUtil.setThreadLocalData(hrv.get());
}
}
AbcApplication.java
public class AbcApplication {
public static void main(String[] args) {
HystrixPlugins.getInstance().registerCommandExecutionHook(new HystrixHook());
SpringApplication.run(Abc.class, args);
}
}
Hope this helps
I've been working on a spring security recently and I know how I can define intercept-url (in Spring Security) dynamically using a Database.
but i need restart my web application to load defined intercept-url from database. But i need to load when i add a new intercept-url to database.
#Component
public class FilterInvocationServiceSecurityMetadataSourceBeanPostProcessor implements BeanPostProcessor {
#Autowired
private FilterInvocationServiceSecurityMetadataSource metadataSource;
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof FilterInvocationSecurityMetadataSource) {
return metadataSource;
}
if(bean instanceof FilterChainProxy.FilterChainValidator) {
return new FilterChainProxy.FilterChainValidator() {
#Override
public void validate(FilterChainProxy filterChainProxy) {
}
};
}
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
#Component("filterInvocationServiceSecurityMetadataSource")
public class FilterInvocationServiceSecurityMetadataSource implements FilterInvocationSecurityMetadataSource, InitializingBean{
private FilterInvocationSecurityMetadataSource delegate;
private RequestConfigMappingService requestConfigMappingService;
private SecurityExpressionHandler<FilterInvocation> expressionHandler;
#Autowired
public FilterInvocationServiceSecurityMetadataSource(CustomWebSecurityExpressionHandler expressionHandler,
RequestConfigMappingService filterInvocationService) {
this.expressionHandler = expressionHandler;
this.requestConfigMappingService = filterInvocationService;
}
public Collection<ConfigAttribute> getAllConfigAttributes() {
return this.delegate.getAllConfigAttributes();
}
public Collection<ConfigAttribute> getAttributes(Object object) {
return this.delegate.getAttributes(object);
}
public boolean supports(Class<?> clazz) {
return this.delegate.supports(clazz);
}
#Override
public void afterPropertiesSet() throws Exception {
List<RequestConfigMapping> requestConfigMappings = requestConfigMappingService.getRequestConfigMappings();
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = new LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>>(requestConfigMappings.size());
for(RequestConfigMapping requestConfigMapping : requestConfigMappings) {
RequestMatcher matcher = requestConfigMapping.getMatcher();
requestMap.put(matcher,requestConfigMapping.getAttributes());
}
this.delegate = new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, expressionHandler);
}
}
#Repository("requestConfigMappingService")
public class JdbcRequestConfigMappingService implements RequestConfigMappingService {
private SecurityFilterMetaDataService securityFilterMetaDataService;
#Autowired
public JdbcRequestConfigMappingService(SecurityFilterMetaDataService securityFilterMetaDataService) {
if (securityFilterMetaDataService == null) {
throw new IllegalArgumentException("securityFilterMetaDataService cannot be null");
}
this.securityFilterMetaDataService = securityFilterMetaDataService;
}
#Override
public List<RequestConfigMapping> getRequestConfigMappings() {
String pattern = "";
String expressionString = "";
List<SecurityFilterMetaData> securityFilterMetaDataList = securityFilterMetaDataService.getByAscOrder("sortOrder");
List<RequestConfigMapping> requestConfigMappings = new ArrayList<>();
for (SecurityFilterMetaData securityFilterMetaData : securityFilterMetaDataList) {
pattern = securityFilterMetaData.getAntPattern();
expressionString = securityFilterMetaData.getExpression();
AntPathRequestMatcher matcher = new AntPathRequestMatcher(pattern);
requestConfigMappings.add(new RequestConfigMapping(matcher, new SecurityConfig(expressionString)));
}
return requestConfigMappings;
}
private static final class RequestConfigMappingMapper implements RowMapper<RequestConfigMapping> {
#Override
public RequestConfigMapping mapRow(ResultSet rs, int rowNum) throws SQLException {
String pattern = rs.getString("ant_pattern");
String expressionString = rs.getString("expression");
AntPathRequestMatcher matcher = new AntPathRequestMatcher(pattern);
return new RequestConfigMapping(matcher, new SecurityConfig(expressionString));
}
}
}
public interface RequestConfigMappingService {
List<RequestConfigMapping> getRequestConfigMappings();
}
public final class RequestConfigMapping {
private final RequestMatcher matcher;
private final Collection<ConfigAttribute> attributes;
public RequestConfigMapping(RequestMatcher matcher, ConfigAttribute attribute) {
this(matcher, Collections.singleton(attribute));
}
public RequestConfigMapping(RequestMatcher matcher, Collection<ConfigAttribute> attributes) {
if (matcher == null) {
throw new IllegalArgumentException("matcher cannot be null");
}
Assert.notEmpty(attributes, "attributes cannot be null or emtpy");
this.matcher = matcher;
this.attributes = attributes;
}
public RequestMatcher getMatcher() {
return matcher;
}
public Collection<ConfigAttribute> getAttributes() {
return attributes;
}
}
At last I found answer. FilterInvocationServiceSecurityMetadataSource must change.
NOTE: Keep in mind that getAttributes will be invoked for every request that Spring Security intercepts so you will most likely want some sort of caching.
#Component("filterInvocationServiceSecurityMetadataSource")
public class FilterInvocationServiceSecurityMetadataSource implements FilterInvocationSecurityMetadataSource, InitializingBean{
private FilterInvocationSecurityMetadataSource delegate;
private RequestConfigMappingService requestConfigMappingService;
private SecurityExpressionHandler<FilterInvocation> expressionHandler;
#Autowired
public FilterInvocationServiceSecurityMetadataSource(CustomWebSecurityExpressionHandler expressionHandler,
RequestConfigMappingService filterInvocationService) {
this.expressionHandler = expressionHandler;
this.requestConfigMappingService = filterInvocationService;
}
public Collection<ConfigAttribute> getAllConfigAttributes() {
return this.delegate.getAllConfigAttributes();
}
public Collection<ConfigAttribute> getAttributes(Object object) {
List<RequestConfigMapping> requestConfigMappings = requestConfigMappingService.getRequestConfigMappings();
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = new LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>>(requestConfigMappings.size());
for(RequestConfigMapping requestConfigMapping : requestConfigMappings) {
RequestMatcher matcher = requestConfigMapping.getMatcher();
requestMap.put(matcher,requestConfigMapping.getAttributes());
}
this.delegate = new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, expressionHandler);
return this.delegate.getAttributes(object);
}
public boolean supports(Class<?> clazz) {
return this.delegate.supports(clazz);
}
#Override
public void afterPropertiesSet() throws Exception {
List<RequestConfigMapping> requestConfigMappings = requestConfigMappingService.getRequestConfigMappings();
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = new LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>>(requestConfigMappings.size());
for(RequestConfigMapping requestConfigMapping : requestConfigMappings) {
RequestMatcher matcher = requestConfigMapping.getMatcher();
requestMap.put(matcher,requestConfigMapping.getAttributes());
}
this.delegate = new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, expressionHandler);
}
}
I have recently started learning OSGi. While experimenting with Apache Aries and OSGi blueprint, I created the following set-up:
Bundle A :
public interface IMessageSender {
String send(String message);
String getServiceName();
}
public interface IMessageSenderFactory {
String name();
IMessageSender create();
}
Bundle B (SMSSenderFactory is exported as a service):
public class SMSSender implements IMessageSender {
public String send(String message) {
return "Sent by SMS : "+message;
}
public String getServiceName() {
return "SMS";
}
}
public class SMSSenderFactory implements IMessageSenderFactory {
public String name() {
return "SMS";
}
public IMessageSender create() {
return new SMSSender();
}
}
Bundle C :
public class BundleManagerImpl implements BundleManager{
BundleContext bundleContext;
Map<IMessageSenderFactory, List<ServiceRegistration>> senders = new HashMap<IMessageSenderFactory, List<ServiceRegistration>>();
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
//reference listener method
public void addSenderFactory(IMessageSenderFactory senderFactory) {
this.senders.put(senderFactory, new ArrayList<ServiceRegistration>());
}
//reference listener method
public void removeSenderFactory(IMessageSenderFactory senderFactory){
List<ServiceRegistration> registeredSenders = this.senders.get(senderFactory);
if (registeredSenders != null){
for (ServiceRegistration serviceRegistration : registeredSenders) {
serviceRegistration.unregister();
}
}
this.senders.remove(senderFactory);
}
#Override
public List<String> listFactories(){
List<String> list = new ArrayList<String>();
for (IMessageSenderFactory senderFactory : senders.keySet()) {
list.add(senderFactory.name());
}
return list;
}
#Override
public void createSenderServiceInstance(String type){
IMessageSender sender = null;
for (IMessageSenderFactory senderFactory : senders.keySet()) {
if (senderFactory.name().equals(type)){
sender = senderFactory.create();
ServiceRegistration registration = bundleContext.registerService(IMessageSender.class.getName(), sender, null);
this.senders.get(senderFactory).add(registration);
}
}
}
}
Bundle D:
public class MessageServiceImpl implements MessageService {
List<IMessageSender> senders = new ArrayList<IMessageSender>();
//reference listener method
public void addSender(IMessageSender sender) {
this.senders.add(sender);
}
//reference listener method
public void removeSender(IMessageSender sender){
this.senders.remove(sender);
}
public List<String> send(String message) {
List<String> list = new ArrayList<String>();
for (IMessageSender sender : this.senders) {
String response = sender.send(message);
list.add(MessageFormat.format("Sent by : {0}; Response : {1}", sender.getServiceName(), response));
}
return list;
}
}
The goal was to allow creation of multiple, variable number of instances of the SMSSender service.
So my questions are:
1 - Is there anything wrong with this approach? I am creating an SMSSender instance, in bundle B and registering it as a service in Bundle C. Would this lead to any issues or does it violate any rule of OSGi?
2 - Are there any other approaches to reaching the same goal?
EDIT:
Bundle E (added later, exports EmailSenderFactory as service)
public class EmailSender implements IMessageSender {
public String send(String message) {
return "Sent by Email : "+message;
}
public String getServiceName() {
return "Email";
}
}
public class EmailSenderFactory implements IMessageSenderFactory {
public String name() {
return "Email";
}
public IMessageSender create() {
return new EmailSender();
}
}
Been stuck on a problem for a while now and searched every possible post but can't find why jersey is ignoring my security annotation?
Basically my Resource Config looks like so
#ApplicationPath("/*")
public class ApplicationResourceConfig extends ResourceConfig {
public ApplicationResourceConfig()
{
packages("com.property");
register(org.springframework.web.context.request.RequestContextListener.class);
register(org.glassfish.jersey.servlet.ServletContainer.class);
register(org.glassfish.jersey.server.spring.SpringLifecycleListener.class);
register(org.glassfish.jersey.server.validation.ValidationFeature.class);
register(org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature.class);
}
}
My Secuirity Context is defined as so;
#Provider
public class Authorizer implements javax.ws.rs.core.SecurityContext {
private final Account account;
private final Session session;
private final Principal principal;
public Authorizer() {
super();
this.account = null;
this.session = null;
this.principal = null;
}
public Authorizer(Account account, Session session) {
this.account = account;
this.session = session;
this.principal = new Principal() {
public String getName() {
return account.getAlias();
}
};
}
#Override
public String getAuthenticationScheme() {
return Authorizer.BASIC_AUTH;
}
#Override
public Principal getUserPrincipal() {
return principal;
}
#Override
public boolean isSecure() {
//return "https".equals(uriInfo.get().getRequestUri().getScheme());
return true;
}
#Override
public boolean isUserInRole(String role) {
if ((role == null) || (session == null) || (!session.isValidSession()) || (this.session.getType() == null) || (account == null))
return false;
return this.session.getType().toString().equals(role);
}
}
Security Filter looks like so
#Provider
#PreMatching
public class SecurityFilter implements ContainerRequestFilter {
#Inject
javax.inject.Provider<UriInfo> uriInfo;
#Autowired
private HibernateSessionFacotry sessionFactory;
#Override
public void filter(ContainerRequestContext request) {
try
{
String sessionKey = request.getHeaderString("Authorization");
Integer uid = request.getHeaderString("From") == null ? null : Integer.parseInt(request.getHeaderString("From"));
if ((sessionKey == null) || (uid == null))
return;
Session session = null;
Account account = null;
session = sessionFactory.getSessionDAO().verifySession(uid, sessionKey);
if (session != null)
account = session.getAccount();
if (
(session != null)
&& (account != null)
&& (session.getSessionKey().equals(sessionKey))
&& (session.getAccountId() == uid)
&& (session.isValidSession())
)
request.setSecurityContext(new Authorizer(account, session));
else
request.setSecurityContext(new Authorizer());
}
catch (Exception ex)
{
//TODO:: ONLY PRINT IN DEBUG MODE
ex.printStackTrace();
return;
}
}
}
My Resources
#Path("/account")
public class AccountImpl implements Account{
#POST
#DenyAll
#Audit
#NotNull #ValidAccount
public com.property.db.entities.account.Account createAccount
(
#NotNull #ValidPostAccount final com.property.db.entities.account.Account account,
#Context HttpServletRequest request
) throws NoSuchAlgorithmException, MandrillApiError, IOException;
}
But for some reason the security annotation #DenyAll gets ignored and I get a 200 response. Any reason why this is happening as I am completely baffled right now.
EDIT::
Just noticed that the security annotation are only ignored from my grizzly servlet any idea why this is happening?
public class WebTest extends JerseyTest {
protected static SimpleDateFormat sdf = null;
protected static GensonProvider gesonProvider = null;
protected static HibernateSessionFacotry sessionFactory = null;
#Override
protected Application configure() {
enable(TestProperties.LOG_TRAFFIC);
enable(TestProperties.DUMP_ENTITY);
return new ApplicationResourceConfig();
}
#Override
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
return new TestContainerFactory() {
#Override
public TestContainer create(final URI baseUri, ApplicationHandler application)
throws IllegalArgumentException {
return new TestContainer() {
private HttpServer server;
#Override
public ClientConfig getClientConfig() {
return null;
}
#Override
public URI getBaseUri() {
return baseUri;
}
#Override
public void start() {
try {
this.server =
GrizzlyWebContainerFactory.create(baseUri);
WebappContext context = new WebappContext("WebappContext", "");
context.addContextInitParameter("contextConfigLocation", "classpath:applicationContext.xml");
context.addListener(org.springframework.web.context.ContextLoaderListener.class);
ServletRegistration registration = context.addServlet("ServletContainer", org.glassfish.jersey.servlet.ServletContainer.class);
registration.addMapping("/*");
registration.setInitParameter("jersey.config.server.provider.packages", "com.property.filters.auditing;com.property.filters.security;com.property.filters.versioning;com.property.resources");
registration.setInitParameter("com.sun.jersey.config.feature.Trace", "true");
context.deploy(server);
} catch (ProcessingException e) {
throw new TestContainerException(e);
} catch (IOException e) {
throw new TestContainerException(e);
}
}
#Override
public void stop() {
this.server.stop();
}
};
}
};
}
public void setUp() throws Exception {
super.setUp();
sdf = new SimpleDateFormat("dd/MM/yyyy");
assertNotNull(sdf);
gesonProvider = new GensonProvider();
assertNotNull(gesonProvider);
sessionFactory = new HibernateSessionFacotry();
assertNotNull(sessionFactory);
}
public void tearDown() throws Exception {
super.tearDown();
}
}