We're trying to have Swagger interact with our resteasy app so that the api will list out on the swagger page. We're using annotations in the Java resources and not a yaml/json file. We want the content to be 'dynamic' or come directly from the resource pages.
When we bring up the swagger page, we get the message 'fetching resource list: //10.155.63.136/nodeMgmt'. When I render the page using firebug, I see that the page itself (index.html) is being 'fed in' to the content.
I think I'm pretty close but am missing one or two small things. I used the example as a guide to what I did: https://github.com/mrj365/RestEasy-3.09-Spring-3.2.5-Swagger2.0
Again, the issue is that the content from the resteasy api is not being fed into the swagger ui. The url in my case is https://10.155.63.92/nodeMgmt/index.html
We're using JBoss 6.4, NO Spring, Resteasy 3.0.7, Swagger jaxrs 1.5.9.
Any help is really appreciated.
Index.html
<script type="text/javascript">
$(function () {
window.swaggerUi = new SwaggerUi({
url: "/nodeMgmt",
dom_id: "swagger-ui-container",
supportedSubmitMethods: ['get', 'post', 'put', 'delete'],
onComplete: function(swaggerApi, swaggerUi){
log("Loaded SwaggerUI");
$('pre code').each(function(i, e) {
hljs.highlightBlock(e)
});
},
onFailure: function(data) {
log("Unable to Load SwaggerUI");
},
docExpansion: "none"
});
web.xml
<!-- Auto scan REST service -->
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/nodes</param-value>
</context-param>
<filter>
<filter-name>ApiOriginFilter</filter-name>
<filter-class>com.sonus.unity.sonusbaserestservice.utils.ApiOriginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ApiOriginFilter</filter-name>
<url-pattern>/index.html</url-pattern>
</filter-mapping>
<!-- if you are using Spring, Seam or EJB as your component model, remove the ResourceMethodSecurityInterceptor -->
<context-param>
<param-name>resteasy.resource.method-interceptors</param-name>
<param-value>
org.jboss.resteasy.core.ResourceMethodSecurityInterceptor
</param-value>
</context-param>
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.sonus.ems.nodemgmt.web.NodeMgmtApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/nodes/*</url-pattern>
</servlet-mapping>
application.java
#ApplicationPath("")
public class NodeMgmtApplication extends SonusBaseRestApplication {
private static final Logger log = Logger.getLogger(NodeMgmtApplication.class);
/**
* Constructor
*/
public NodeMgmtApplication() {
super();
try {
//TODO Swagger
// Used for defining swagger
BeanConfig beanConfig = new BeanConfig();
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8080");
beanConfig.setVersion("1.5.9");
beanConfig.setBasePath("/nodeMgmt");
beanConfig.setResourcePackage("com.sonus.ems.nodemgmt.web");
//beanConfig.setPrettyPrint(true);
beanConfig.setScan(true);
addService(new NodeMgmtAuthorizationFilter());
addService(new NodeMgmtRestService());
// Swagger
addService(new ApiListingResource());
addService(new SwaggerSerializers());
} catch (Exception e) {
log.error("NodeAdminApplication: Could not instantiate singletons " + e);
}
}
resource.java
#Path("/")
#Api(value = "/", description = "Node operations", produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
public class NodeMgmtRestService {
private static final Logger log = Logger.getLogger(NodeMgmtRestService.class);
private static final String NODES = "nodes";
private static final String ID = "id";
NodeMgmtServiceProvider nodeMgmtServiceProvider = new NodeMgmtServiceProvider();
Service nodeMgmtService;
#GET
#Path("/{version}")
#Produces(MediaType.APPLICATION_JSON)
#ApiOperation(value = "Get all nodes", notes = "Returns a list of node", response = String.class, responseContainer="List")
public Response getNodes(
#ApiParam(value = "Version of api (1.0)", required = true) #PathParam("version") String version,
#ApiParam(value = "Filter by ", required = true) #QueryParam("filterParam") String filterParam,
#ApiParam(value = "Filter value ", required = true) #QueryParam("filterValue") String filterValue) {
List<Node> nodeList = new ArrayList<Node>();
List<Object> nodeJsonList = new ArrayList<Object>();
Map<String, List<Object>> nodeJsonMap = new HashMap<String, List<Object>>();
ObjectMapper objectMapper = new ObjectMapper();
Map<String, String> responseId = new HashMap<String, String>();
JsonNodeDao jsonNodeDao = new JsonNodeDao();
Swagger API key
public class ApiOriginFilter implements Filter {
#Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
// Add access to the header
res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, PATCH, OPTIONS");
res.addHeader("Access-Control-Allow-Headers", "Content-Type, api_key, Authorization");
//res.addHeader("Access-Control-Allow-Headers", "Origin, X-Atmosphere-tracking-id, X-Atmosphere-Framework, X-Cache-Date, Content-Type, api_key, Authorization, X-Atmosphere-Transport, x-requested-with, Total-Count, Total-Pages, Error-Message, *");
//res.addHeader("Access-Control-Request-Headers", "Origin, X-Atmosphere-tracking-id, X-Atmosphere-Framework, X-Cache-Date, Content-Type, api_key, Authorization, X-Atmosphere-Transport, x-requested-with, Total-Count, Total-Pages, Error-Message, *");
chain.doFilter(request, response);
}
#Override
public void destroy() {
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
Related
I am using Spring security + Spring core and combination with CXF for my restful.
Below are configs:
web.xml for CXF config:
<!-- Spring configuration for ContextLoaderListener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- CXF configuration for resful webservices -->
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
config CXF endpoint (context.xml)
<!-- configure for restful endpoint for application services as web authentication... -->
<jaxrs:server id="ApplicationServices"
address="/Application">
<jaxrs:serviceBeans>
<ref bean="ControllerImpl" />
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider" />
</jaxrs:providers>
<jaxrs:features>
<bean id="loggingFeature"
class="org.apache.cxf.feature.LoggingFeature">
<property name="prettyLogging" value="true" />
</bean>
<ref bean="swagger2Feature" />
</jaxrs:features>
</jaxrs:server>
spring security config - filter
public class AuthenticationFilter extends AbstractAuthenticationProcessingFilter {
AuthenticationFilter(final RequestMatcher requiresAuth) {
super(requiresAuth);
}
#Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {
//Optional<String> tokenParam = Optional.ofNullable(httpServletRequest.getHeader(AUTHORIZATION)); //Authorization: Bearer TOKEN
String token= StringUtils.isNotEmpty(httpServletRequest.getHeader(AUTHORIZATION))? httpServletRequest.getHeader(AUTHORIZATION) : "";
token= StringUtils.removeStart(token, "Bearer").trim();
Authentication requestAuthentication = new UsernamePasswordAuthenticationToken(token, token);
return getAuthenticationManager().authenticate(requestAuthentication);
}
#Override
protected void successfulAuthentication(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain, final Authentication authResult) throws IOException, ServletException {
SecurityContextHolder.getContext().setAuthentication(authResult);
chain.doFilter(request, response);
}
}
spring security config - provider
#Component
public class AuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
#Autowired
UserTokenService userTokenService;
#Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
//
}
#Override
protected UserDetails retrieveUser(String userName, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
Object token= usernamePasswordAuthenticationToken.getCredentials();
return Optional
.ofNullable(token)
.map(String::valueOf)
.flatMap(userTokenService::findByToken)
.orElseThrow(() -> new UsernameNotFoundException("Cannot find user with authentication token=" + token));
}
}
spring security config - SecurityConfiguration
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final RequestMatcher PROTECTED_URLS = new OrRequestMatcher(
new AntPathRequestMatcher("/services/**"));
AuthenticationProvider provider;
public SecurityConfiguration(final AuthenticationProvider authenticationProvider) {
super();
this.provider = authenticationProvider;
}
#Override
protected void configure(final AuthenticationManagerBuilder auth) {
auth.authenticationProvider(provider);
}
/**
* we don't need provide this service for now because we are using Vaadin
*/
#Override
public void configure(final WebSecurity webSecurity) {
webSecurity.ignoring().antMatchers("/token/**");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().exceptionHandling().and()
.authenticationProvider(provider)
.addFilterBefore(authenticationFilter(), AnonymousAuthenticationFilter.class).authorizeRequests()
.requestMatchers(PROTECTED_URLS).authenticated().and().csrf().disable().formLogin().disable()
.httpBasic().disable().logout().disable();
}
#Bean
AuthenticationFilter authenticationFilter() throws Exception {
final AuthenticationFilter filter = new AuthenticationFilter(PROTECTED_URLS);
filter.setAuthenticationManager(authenticationManager());
// filter.setAuthenticationSuccessHandler(successHandler());
return filter;
}
#Bean
AuthenticationEntryPoint forbiddenEntryPoint() {
return new HttpStatusEntryPoint(HttpStatus.FORBIDDEN);
}
}
findByToken
#Override
public Optional<User> findByToken(String token) {
UserToken userToken = userTokenDAO.findByToken(token);
if (userToken != null) {
User user = new User(userToken.getUserId(), userToken.getUserPassword(), true, true, true, true,
AuthorityUtils.createAuthorityList("USER"));
return Optional.of(user);
}
return Optional.empty();
}
However filter does not work. The request still allows comming without any validation by spring security.
The request like:
curl -X POST "http://localhost:8080/my-app/services/Application/ControllerImpl/myservice1" -H "accept: application/json" -H "Content-Type: application/json" -d "string"
There is no exception or error. The above request returns 200 (OK). I expected to fail because of no bearer token on the request.
How can we combine Spring security (using bearer token method) and CXF ?
Based on discussion in the comments, it is clear spring security filter chain is not getting configured.
Can you please add the following to your web.xml as well and see if the execution is hitting AntPathRequestMatcher matches method
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
I have recently upgraded my code from Struts 1 to Struts 2 and the app is not working after deploying it in my test environment (Linux box). The test env has 3 server instances with different url for each instance. I have deployed my new code(Struts 2) in instance#2 and instance#1 and #3 has old code(Struts 1)
The problem is once i login to the url's of Instance 1 and 3, I am successfully able to login to Instance #2.
But when I login to Instance #2 url directly, struts 2 action is not being invoked and stays in login page itself
web.xml
<!-- Note how the Application Security Team's security filter is listed
FIRST! -->
<filter-name>AppSecSecurityFilter</filter-name>
<filter-class>com.qwest.appsec.TomcatSecurityFilter</filter-class>
<!-- Required. The name for this application -->
<init-param>
<param-name>applicationName</param-name>
<param-value>NATE</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>AppSecSecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/does_not_exist_jaasinit.html</form-login-page>
<form-error-page>/appsec/access_denied_en.html</form-error-page>
</form-login-config>
</login-config><filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping><session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
Struts.xml:
<struts><package name="loginPackage" namespace="/" extends="struts-default">
<action name="nateLoginAction" class="com.wireless.nate.actions.LoginAction">
<result name="success">creditNate.jsp</result>
<result name="error">login.jsp </result>
<result name="input">login.jsp</result>
</action>
</package></struts>
LoginAction.java
public class LoginAction extends ActionSupport implements
ServletRequestAware,ServletResponseAware
{
private static final long serialVersionUID = -3510995405804328464L;
private Logger logger = Logger.getLogger(this.getClass());
HttpServletRequest request;
HttpServletResponse response;
LoginActionForm loginActionForm;
ActionContext context;
ActionSupport actionSupport;
public LoginActionForm getLoginActionForm() {
return loginActionForm;
}
public void setLoginActionForm(LoginActionForm loginActionForm) {
this.loginActionForm = loginActionForm;
}
#Override
public void setServletResponse(HttpServletResponse response) {
this.response=response;
}
#Override
public void setServletRequest(HttpServletRequest request) {
this.request=request;
}
public String execute() throws Exception
{
System.out.println("inside action execute method");
logger.debug("+execute()");
ValueStack stack = context.getValueStack();
Map<String, Object> context = new HashMap<String, Object>();
// Get the html form fields from the cookies
String salesCode = "";
String loginUserId = "";
javax.servlet.http.Cookie[] cookies = request.getCookies();
javax.servlet.http.Cookie thisCookie = null;
if (null != cookies)
{
for (int i = 0; i < cookies.length; i++)
{
thisCookie = cookies[i];
logger.debug("request.getCookies():");
logger.debug(" cookies[" + i + "].getName()=" + cookies[i].getName());
logger.debug(" cookies[" + i + "].getValue()=" + cookies[i].getValue());
if (thisCookie.getName().equals("salesCode"))
{
salesCode = cookies[i].getValue();
}
else if (thisCookie.getName().equals("user"))
{
loginUserId = cookies[i].getValue();
}
}
}
loginActionForm.setSalesCode(salesCode.toUpperCase());
loginActionForm.setUser(loginUserId);
context.put("loginActionForm", loginActionForm);
stack.push(context);
return SUCCESS;
}
public void validate(){
System.out.println("inside action validate method");
context = ActionContext.getContext();
actionSupport=(ActionSupport)context.getActionInvocation().getAction();
if(loginActionForm.getUser() == null || loginActionForm.getUser().length() == 0){
addFieldError("user.required","User name is required");
}
if(loginActionForm.getPassword() == null || loginActionForm.getPassword().length() ==0){
addFieldError("password.required","Password is required");
}
}
}
I am new to spring boot. I have implemented Spring Security with oAuth2 and get acesstoken successfully from spring Security. But when I try to request with token with "Authorization" header..
config.headers["Authorization"] = 'Bearer 0d634d2b-3900-4ca4-a462-cf729e8d0c72';
and my CORS filter is as :
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class RequestFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT,DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
if (request.getMethod()!="OPTIONS") {
chain.doFilter(req, res);
} else {
}
}
#Override
public void destroy() {
}
}
But still it given CORS issue.
Please help me where I am wrong.
Problem solve. I have send token as wrong way
config.headers["Authorization"] = 'Bearer 0d634d2b-3900-4ca4-a462-cf729e8d0c72';
right way is:
config.headers.authorization = 'Bearer 0d634d2b-3900-4ca4-a462-cf729e8d0c72';
Try to set your Access-Control-Allow-Headers like this:
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Authorization, Content-Type");
In jsf2 when I have PROJECT_STAGE = Production my h:head part is not refreshed. When I change it to Development, then everything works fine. How to force the head part for being refreshed?
The h:head is in template.xhtml.
template.xhtml:
<h:head>
<meta name="description" content="#{metaBean.metaDescription}" />
<meta name="keywords" content="#{metaBean.metaKeywords}" />
</h:head>
web.xml
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<!-- <param-value>Development</param-value>-->
<param-value>Production</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
<param-value>0</param-value>
</context-param>
...Or How to make dynamic meta description in other way?
Thank you
You can use meta filter like this
public class HtmlMetaFilter implements Filter {
private List<String> metaNames = null;
private List<String> metaValues = null;
private int metaSize = 0;
#Override
public void destroy() {
// logger.info("html meta filter destroyed.");
}
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse)response;
for(int i = 0; i < metaSize; i++) {
res.setHeader(metaNames.get(i), metaValues.get(i));
}
chain.doFilter(request, res);
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
metaNames = Configuration.getInstance().getList("//configuration/web-app/html-meta/name");
metaValues = Configuration.getInstance().getList("//configuration/web-app/html-meta/value");
if(metaNames != null && metaValues != null) {
metaSize = Math.min(metaNames.size(), metaValues.size());
}
// logger.info("html meta filter initialized.");
}
}
If you want to change it dynamically, then you need to set the different data in init method from your bean file.
I've found answer on this post: title in h:head rendered before render response phase?
It's enough to use event preRenderView and prepare necessary values in it.
hi i am using jsf2.0, prettyfaces,primesfaces
i have created a filter which monitor user session
#WebFilter(urlPatterns= {"*.xhtml"} , dispatcherTypes = {DispatcherType.REQUEST})
public class Authentication implements Filter {
#Override
public void init(FilterConfig config) throws ServletException {
System.out.println("[Authentication Filter] : init Method");
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
PrettyContext context = PrettyContext.getCurrentInstance(request);
if (!(context.getCurrentMapping().getId().equals("login")) && (session == null || session.getAttribute("username") == null)) {
{
response.sendRedirect(request.getContextPath()+"/login");
}
else {
chain.doFilter(req, res); // Logged-in user found, so just continue request.
}
#Override
public void destroy() {}
}
web.xml
<welcome-file-list>
<welcome-file>/</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
pretty-config.xml
<url-mapping id="home">
<pattern value="/" />
<view-id value="index.xhtml" />
</url-mapping>
when i use dispatcherTypes = {DispatcherType.REQUEST} i get null pointer exception on
context.getCurrentMapping().getId() this statement which is using in if statement see above
but when i dispatcherTypes = {DispatcherType.FORWARD} its working fine for me
what's happening can any body guide me ? thanks
and i want to know different between DispatcherType.REQUEST and DispatcherType.FORWARD ,
an other Question is when i use FacesContext.getCurrentInstance().getExternalContext().invalidateSession(); for destoring session
and if i press BACK button from browser it takes me on previous page why browser shows me privous page?, i want login page on BAck button
thanks.
PrettyFaces implements URL rewriting by intercepting incoming requests in a Servlet filter and then forwarding it to the real URL.
The DispatchType of a filter configures for which kind of request the filter should be applied. The default is REQUEST which is the usual case. If you set it to FORWARD it is only applied to requests that are internally forwarded (which is what PrettyFaces does).
In case of REQUEST you are getting the NPE because your filter executes before the PrettyFaces filter and so you cannot access the PrettyContext.
It is absolutely fine for you to use FORWARD in your case. The only thing that you have to remember is that HttpServletRequest.getRequestURI() will return the real URL instead of the pretty one for forwarded requests.
Your back button problem is probably related to caching. If you don't set correct caching heads, the browser will cache the last page and so pressing BACK will simply redisplay the last page without sending a request to the server.