I am designing a set of REST APIs for accessing the URLs. As per my requirement there are two URLs:
http://localhost:3126/securitydemo/webapi/db/students
to view all the students no access required and
http://localhost:3126/securitydemo/webapi/db/students/1
only ROLE_USER are allowed.
My Spring Security configuration:
<http auto-config="true" use-expressions="true">
<intercept-url pattern="**/students/*" access="hasRole('ROLE_USER')" />
<http-basic/>
</http>
If I use the pattern **/students/* no basic security popup occurs. If I use /** it's working properly.
How can I intercept the two URLs with different security levels?
My REST service class:
#Path("/db")
#Produces(MediaType.APPLICATION_JSON)
public class StudentService {
static StudentDao data = new StudentDaoImpl();
#Path("/students")
#GET
public Response getStudents(){
GenericEntity<List<Student>> entity = new GenericEntity<List<Student>>(data.getAllStudents()){};
return Response.ok(entity).build();
}
#Path("/students/{id}")
#GET
public Response getStudent(#PathParam("id") int id){
return Response.ok(data.getStudent(id)).build();
}
}
try this
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/securitydemo/webapi/db/students/1/**" access="hasRole('ROLE_USER')" />
<http-basic/>
</http>
Related
I want to host a WCF Rest Service with multiple contracts via mono each implemented in a separate partial class. I read many posts on similar issues, yet there was no solution for mono. I incorporated or at least tested all suggestions I could find and by now my code looks a lot like other solutions, yet does not work.
The application runs successfully on my local machine but throws an error once I deploy it via mono.
Service 'MyWebServiceEndpoint' implements multiple ServiceContract types, and no endpoints are defined in the configuration file.
Here is one of the endpoints with the contract. All the others are very much like this one. They all are a partial class MyWebServiceEndpoint implementing another contract.
namespace MyServer.MyEndPoints {
public partial class MyWebServiceEndpoint : INotificationEndpoint {
public string GetNotifications(int limit) {
// Do stuff
}
}
[ServiceContract]
public interface INotificationEndpoint {
[OperationContract]
[WebGet]
string GetNotifications(int limit);
}
}
My App.config looks like this. I removed the IP and port, as they are the server address.
<system.serviceModel>
<services>
<service name="MyServer.MyEndPoints.MyWebServiceEndpoint" behaviorConfiguration="WebService.EndPoint">
<host>
<baseAddresses>
<add baseAddress="http://ip:port>"/>
</baseAddresses>
</host>
<endpoint address="/message"
binding="webHttpBinding"
contract="MyServer.MyEndPoints.IMessageEndpoint"
behaviorConfiguration="WebBehavior"/>
<endpoint address="/music"
binding="webHttpBinding"
contract="MyServer.MyEndPoints.IMusicEndpoint"
behaviorConfiguration="WebBehavior"/>
<endpoint address="/notification"
binding="webHttpBinding"
contract="MyServer.MyEndPoints.INotificationEndpoint"
behaviorConfiguration="WebBehavior"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WebService.EndPoint">
<serviceMetadata httpGetEnabled="True" />
<serviceDebug includeExceptionDetailInFaults="True"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="WebBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
I open the service in C# like this.
WebServiceHost = new WebServiceHost(typeof(MyWebServiceEndpoint));
WebServiceHost.Open();
The Error message I receive on mono is:
Unhandled Exception:
System.InvalidOperationException: Service 'MyWebServiceEndpoint' implements multiple ServiceContract
types, and no endpoints are defined in the configuration file. WebServiceHost can set up default
endpoints, but only if the service implements only a single ServiceContract. Either change the
service to only implement a single ServiceContract, or else define endpoints for the service
explicitly in the configuration file. When more than one contract is implemented, must add base
address endpoint manually
I hope you have some hints or someone knows how to solve the issue. Thank you already for reading up to here.
I am not familiar with Mono, Does the Mono support Webconfig file? I advise you to add the service endpoint programmatically.
class Program
{
/// <param name="args"></param>
static void Main(string[] args)
{
WebHttpBinding binding = new WebHttpBinding();
Uri uri = new Uri("http://localhost:21011");
using (WebServiceHost sh = new WebServiceHost(typeof(TestService),uri))
{
sh.AddServiceEndpoint(typeof(ITestService), binding, "service1");
sh.AddServiceEndpoint(typeof(IService), binding, "service2");
ServiceMetadataBehavior smb;
smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb == null)
{
smb = new ServiceMetadataBehavior()
{
HttpGetEnabled = true
};
sh.Description.Behaviors.Add(smb);
}
sh.Opened += delegate
{
Console.WriteLine("service is ready");
};
sh.Closed += delegate
{
Console.WriteLine("service is closed");
};
sh.Open();
Console.ReadLine();
sh.Close();
}
}
}
[ServiceContract]
public interface ITestService
{
[OperationContract]
[WebGet]
string GetData(int id);
}
[ServiceContract]
public interface IService
{
[OperationContract]
[WebGet]
string Test();
}
public class TestService : ITestService,IService
{
public string GetData(int id)
{
return $"{id},";
}
public string Test()
{
return "Hello " + DateTime.Now.ToString();
}
}
Result.
According to the official documentation, we had better not use Partial class.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/samples/multiple-contracts
Besides, we could consider launching multiple service host for every service implemented class.
Feel free to let me know if the problem still exists.
The requirement is SOAP WSDL Url and Endpoint URL must be different from each other. Im using Apache Camel and Apache CXF below is my blueprint but when i request at port 8043 there is no wsdl there when i change it to 9143 wsdl is there.
Need to expose wsdl on url: http://0.0.0.0:8043/Services/Interface/FSServices/FSServices.serviceagent?wsdl
Endpoint URL be: http://0.0.0.0:9143/Services/Interface/FSServices/FSServices.serviceagent/PortTypeEndpoint1/
<cxf:cxfEndpoint
address="http://0.0.0.0:8043/Services/Interface/FSServices/FSServices.serviceagent"
id="fsEndpoint" serviceClass="pk.com.herman.fs.operation.PortType">
<cxf:properties>
<entry key="publishedEndpointUrl" value="http://0.0.0.0:9143/Services/Interface/FSServices/FSServices.serviceagent/PortTypeEndpoint1/"/>
</cxf:properties>
</cxf:cxfEndpoint>
Weird requirement. You could do this by adding an interceptor which disables the WSDLGetInterceptor interceptor.
Add Interceptor
<bean id="removeWSDLinterceptor"
class="my.package.RemoveWSDLInterceptor" />
<cxf:cxfEndpoint address="http://0.0.0.0:8043/Services/Interface/FSServices/FSServices.serviceagent"
id="fsEndpoint" serviceClass="pk.com.herman.fs.operation.PortType">
<cxf:inInterceptors>
<ref bean="removeWSDLinterceptor" />
</cxf:inInterceptors>
</cxf:cxfEndpoint>
Interceptor
public class RemoveWSDLInterceptor extends AbstractPhaseInterceptor<Message>
{
public RemoveWSDLInterceptor() {
super(Phase.RECEIVE);
}
public void handleMessage(Message message) {
WSDLGetInterceptor getWSDLInterceptor = null;
InterceptorChain chain = message.getInterceptorChain();
for(Iterator<Interceptor<? extends Message>> iter = chain.iterator(); iter.hasNext();) {
Interceptor getWSDLInterceptor = iter.next();
if (interceptor instanceof WSDLGetInterceptor) {
getWSDLInterceptor = (WSDLGetInterceptor) interceptor;
}
}
chain.remove(getWSDLInterceptor);
}
public void handleFault(Message messageParam) {
}
}
And then you can add a small jetty route to return the WSDL statically.
<route>
<from uri="jetty://http://0.0.0.0:9143" />
<to uri="language:constant:resource:file:/path/to/your/wsdlfile.wsdl"/>
</route>
I am trying to secure my REST services using spring security.My problem is ,I have stuck at authentication entry point.even though I have configured a UsernamePasswordAuthenticationFilter,execution flow could not reach there.
Below is the XML configuration
<sec:http create-session="stateless" auto-config="false"
authentication-manager-ref="authenticationManager"
entry-point-ref="http403EntryPoint"
>
<sec:form-login
login-processing-url="/login"
password-parameter="password"
username-parameter="username"
/>
<!-- <sec:custom-filter ref="tokenCreatorAndValidator" position="FORM_LOGIN_FILTER" /> -->
<sec:intercept-url pattern="/**"
method="POST"
access="ROLE_USER"
/>
</sec:http>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider user-service-ref="authenticatorDAO">
</sec:authentication-provider>
</sec:authentication-manager>
<bean id="http403EntryPoint"
class="com.app.login.RestAuthenticationEntryPoint" />
code for AuthenticationEntryPoint is given below.
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint{
#Override
public void commence( HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException ) throws IOException{
System.out.println("in RestAuthenticationEntrypoint\n--------------------------------------\n");
response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized" );
}
}
can anybody tell me what I m doing wrong here?
Sorry cannot post comments hence posting this as answer.
Check if ExceptionTranslationFilter is getting called in your exiting configuration.
OR
Did you injected http403EntryPoint in ExceptionTranslationFilter?
<bean id="etf" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="http403EntryPoint"/>
</bean
>
social to integrate my web application with Facebook, now when the user is logged-in in my web application using Facebook login, I am able to read data from his/her profile but whenever I am trying to perform some write operation like update status or publish a post on user's wall , I am getting an InsufficientPermissionException.
My Login form is:
<form name="fb_signin" id="fb_signin" action="${pageContext.request.contextPath}/auth/facebook">
<input type="hidden" name="scope" value="email,publish_stream,read_stream,user_status,user_photos,publish_actions,offline_access" />
<button class="btn btn-facebook" type="submit"> <i class="icon-facebook"></i>facebook</button>
</form>
The required part of config for this operation is:
<bean id="userIdSource" class="org.springframework.social.security.AuthenticationNameUserIdSource"/>
<bean id="facebookApiHelper" class="org.springframework.social.facebook.config.support.FacebookApiHelper">
<constructor-arg index="0" ref="usersConnectionRepository"/>
<constructor-arg index="1" ref="userIdSource"/>
</bean>
<bean id="connectionFactoryLocator" class="org.springframework.social.security.SocialAuthenticationServiceRegistry">
<property name="authenticationServices">
<list>
<bean class="org.springframework.social.facebook.security.FacebookAuthenticationService">
<constructor-arg value="${facebook.app.id}" />
<constructor-arg value="${facebook.app.secret}" />
<!-- Important: The next property name changed from "scope" to "defaultScope" in 1.1.0.M4 -->
<property name="defaultScope" value="email,publish_actions,publish_stream,read_stream,user_status,user_photos,offline_access" />
</bean>
</list>
</property>
</bean>
And now my controller is:
public class FacebookOperationController {
private static final Logger logger = LoggerFactory.getLogger(FacebookOperationController.class);
#Autowired
protected FacebookApiHelper facebookApiHelper;
#Autowired
UserIdSource userIdSource;
private UsersConnectionRepository usersConnectionRepository;
#Autowired
public FacebookOperationController(UsersConnectionRepository usersConnectionRepository)
{
this.usersConnectionRepository = usersConnectionRepository;
}
#RequestMapping(method = RequestMethod.GET)
public String shareWithFacebook(WebRequest request,Model model){
Facebook facebook = facebookApiHelper.getApi();
Connection<Facebook> connection = usersConnectionRepository.createConnectionRepository(userIdSource.getUserId()).findPrimaryConnection(Facebook.class);
//connection.updateStatus("hello world");
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.set("link", "www.equinoxrar.com");
map.set("name", "Hi This is a Test Post");
map.set("caption", "Link Caption");
map.set("description", "Loooooo....ng description here");
map.set("message", "hello world");
// THE BELOW LINES ARE THE CRITICAL PART I WAS LOOKING AT!
map.set("picture", "http://www.imageRepo.com/resources/test.png"); // the image on the left
//map.set("actions", "{'name':'myAction', 'link':'http://www.bla.com/action'}"); // custom actions as JSON string
//String a = facebook.publish(userIdSource.getUserId(), "feed", map);
String b = connection.getApi().publish(userIdSource.getUserId(), "feed", map);
//publish(userIdToPostTo, "feed", map);
return "tilesname";
}
}
I am able to perform read operation from this Controller but getting an InsufficientPermissionException for any write operation. Can anyone have any idea? The Exception I am getting here is:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.social.InsufficientPermissionException: Insufficient permission for this operation.
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:948)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
Actually I have solved the problem, I am able to post in facebook from my web app when I used the app admin login, but for test facebook apps only admin/developers/testers added to the facebook app can post, for all other we have to submit details (login review) of my app to facebook, once facebook approve the same, then it will be open for all usrs.
Could you please post more of the stacktrace to get some more into the error?
You could also try creating a org.springframework.social.facebook.api.FacebookLink object and posting using
facebook.feedOperations().postLink("i'm posting", link);
I'm integrating Symfony DIC in a zend framework application, that's going fine except for parent services.
In my DIC config I have a parent service PC_Service which will be extended by all my services.
The problem is that the entity manager is not available (NULL) in the services that extend PC_Service. When I inject the entitymanager via service.stats the entitymanger is set correctly.
...
<service id="pc.service" class="PC_Service" abstract="true">
<call method="setEntityManager">
<argument type="service" id="doctrine.entitymanager" />
</call>
</service>
...
<service id="service.stats" class="Application_Service_Stats" parent="pc.service" />
...
PC_Service
abstract class PC_Service
{
protected $_em;
public function setEntityManager($entityManager)
{
$this->_em = $entityManager;
}
}
Application_Service_Stats
class Application_Service_Stats extends PC_Service
{
... $this->_em should be set here.
}
I hope someone can tell me what I'm doing wrong.
Don't know if it's a typo but it should be doctrine.orm.default_entity_manager or doctrine.orm.entity_manager (alias of the previuos):
<service id="pc.service" class="PC_Service" abstract="true">
<call method="setEntityManager">
<argument type="service" id="doctrine.orm.default_entity_manager" />
</call>
</service>
The solution is to compile the service container near the end of the ZF bootstrap. This process has a step called ResolveDefinitionTemplatesPass which patches in the calls from parent services.
This is typically done by the Symfony Kernel, but of course it isn't present in a ZF integration.
protected function _initServiceContainerCompilation()
{
// Wait for the SC to get built
$this->bootstrap('Services');
// Doctrine modifies the SC, so we need to wait for it also
$this->bootstrap('Doctrine');
// Compiling the SC allows "ResolveDefinitionTemplatesPass" to run,
// allowing services to inherit method calls from parents
$sc = $this->getResource('Services');
$sc->compile();
}