I'm working on a WCF Service that is called by our other softwars to send bug information to our database. The problem is that, since it is an online service, it isn't safe, so I was wondering if it's possible to the service to request a password (i.e. when we call the service, we have to configure the password or something like that).
I googled about it, but it all seemed so complex for such 开发者_StackOverflow社区a simple thing ... can you guys help me out?
Edit:
The idea is to authenticate through my software, without the need of a user login.
Another option is to implement your own security. Here's a basic example.
WCF Service
In your service, change it's ServiceBehavior
's InstanceContextMode
to PerSession
and ConcurrencyMode
to Single
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
public class SomeService : ISomeService
{
// ...
}
Add a Username
and Password
property in your service.
public string UserName { [OperationContract] get; [OperationContract] set; }
public string Password { [OperationContract] get; [OperationContract] set; }
Add a private method for checking a security.
public void CheckSecurity()
{
if ((this.UserName == null || this.Password == null) ||
this.UserName == "username" && this.Password == "password"))
{
throw new FaultException("Unknown username or incorrect password.");
}
}
Then call the CheckSecurity
method in each of your service class constructor method.
public SomeServiceMethod1()
{
this.CheckSecurity();
// some method codes
}
Client Application
In your client application code, set the service username and password for every instance, or create a static class that will do this for you.
You might also try to use encryption in the username and password to add security.
Note that this is just to add another option for you that might fit your needs but you should always try to use the Microsoft way of doing things.
You can use the ASP.NET Membership provider to authenicate clients. There is an article on MSDN describing how to achieve that.
Unfrotunately security is never simple. For your requirements, have a look at UserNamePasswordClientCredential and UserNamePasswordServiceCredential. They might be sufficient.
All of the answers below are good, but it will depend on who's consuming your WCF service.
For example, I know a WCF service that's consumed by a iPhone application via REST, and some of the schemes above would be very difficult if not impossible to implement. It used something similar to stefan's solution of a session key passed in the message header.
There are many ways to handle this scenario.
Fredrik and stefan's answers together could yield an authentication method and authorization (via token) but you would have to write the login page, db, code, checks, enforcement, token creation, token embedding and token validation logic yourself.
PaulF's suggestion is probably less work because you can use features built into WCF to carry the credentials in the message transport. Could skip the token creation, token embedding and token validation logic pieces.
If you plan on supporting many different devices I would recommend looking into OpenID, Windows Identity Foundation, Azure Authentication Service, etc. - These are a bit more complicated to setup but provide a solid, standards based and flexible method for passing around credentials. Passive Federation is a good keyword if you want to go that route.
Unfortunately, as Paul said, security is never simple. You have to think about how you authenticate, what you need to know about the person in the service/app, how you pass those credentials other apps/services securely, how they know you are really you and vica versa... Once you get federated authentication setup you no longer have to worry about a lot of those things for this service and others going forward...
Authenticating the software which is generating requests to a service is inherently a very difficult problem, far harder than authenticating a human user. The problem arises from the need to store secret information to be used to construct the credentials sent as the basis for authentication.
When authenticating a human user you can rely on them being able to store a secret (such as a PIN or password) in a data store (the wet grey matter between their ears) which only they have access to.
When you are trying to authenticate some body of software executing in an environment over which you have no control, there is no equivalent storage place for a secret which gives you any assurance that only your software has access to it. So in general there is no way for your software to generate a request which reliably proves that it was generated by your software and not something else.
Your only options are:
- Find some way to provide a secret store to the software at runtime, such as a PIN-protected smart card which has to be used in conjunction with your client application.
- Rely on security by obscurity, accepting that this can only make spoofing a bit harder and more time-consuming for an attacker, but will not defeat someone determined to break your authentication scheme.
What you need is to implement custom password validation. Here are good articles about that: UserNamePasswordValidator and CodeProject.
We use same thing in our project, but API key is used instead of Username. Password can be anything in this case.
精彩评论