I need to edit the principal id that will be returned to a cas client application.
The principal I need to edit is returned from an external idp which I do not own and its format is like this:
Id: idp autogenerated ID having no meaning for my setup
Attributes:
... Some attributes I do not need ...
**ImportantId**(this is the property I need)
I have read the official documentation so from my understanding the related part of my service json file should be:
...
"usernameAttributeProvider" : {
"#class" : "com.mypackage.cas.principal.MyCustomRegisteredServiceUsernameProvider",
"canonicalizationMode" : "NONE"
In my custom UserNameProvider class, I need to access db in order to get my setup specific username based on the importantId I mentioned above, so I need to do something like this :
public class MyCustomRegisteredServiceUsernameProvider implements RegisteredServiceUsernameAttributeProvider {
#Autowired
UsersService usersService;
#Override
public String resolveUsername(Principal principal, Service service, RegisteredService registeredService) {
// String importantId = ...getting it from principal attributes..
return usersService.getUserNameFromImportant(importantId);
}
}
The problem is that Autowired annotation unfortunately is not working, thus my UsersService is not initialized resulting in a NPE at runtime.
So, firstly I would like to know why my approach is not working and secondly what is the cas "official" way to achieve this behavior?
Cas Version: 5.3.4 Cas overlay template
Env: W10 x64, Java 8
Deployed on Wildfly 12
So, firstly I would like to know why my approach is not working
...because such providers are not spring-managed beans. They are serialized objects found off of JSON documents, and such and never pass through the Spring runtime.
and secondly what is the cas "official" way to achieve this behavior?
One possible workaround would be to remove the injected field and do this in your resolveUsername method:
var appContext = ApplicationContextProvider.getApplicationContext();
var usersService = appContext.getBean("bean-name", UsersService.class);
return usersService.getUserNameFromImportant(importantId);
I have a web form that enables one to update the appliaction.properties, so that user does not have to go to the file and edit it. I wants to load the value from the application.properties file and display in the web form textfield. After the user edit the some changes, user can update the application.properties file.
Question - How can I bind my web form to application.properties file other than using #value in Spring? As the key/value pairs might be updated through web form, I believe #value is not the right choice.
The application properties are for the settings the application needs to load when it starts up, and then connects to a database for example, with the username and password specified in that file (although environment variables can also be used.)
You shouldn't really edit this file at run-time, with the exception of using the Refresh Scope annotation. But I don't advise you do that as it's fairly hard in practice to achieve an application which supports changing configuration at run-time.
There is also Spring Cloud Config server for reloading properties at run-time and that provides a REST API although you mainly just use git with that one.
But the key is here that they are all mentioning configuration which is only something developers do. I also don't think you want to use the filesystem for storing your state, much rather have database. There are many reasons to use a file system over a database I won't go into them now.
I will make the assumption you are a beginner looking at your rep. Best advice I can give you is to watch what everyone else is doing and learn from that first. Most of the time people are all doing similar things because it is the right thing to do. If you can't find anybody else changing properties files based on form submissions in their spring app but rather using databases you probably want to go with the database.
We were in a similar situation last month where client need update in configuration file in run time.
We created a central Spring component that loads all properties from file using #Value
#Component
public class ConfigurationManagerComponent{
#Value("conf.username")
private String userName;
#Value("conf.email");
private String email;
/*
* All your attributes
*/
//getters and setters
public String getUserName(){
return this.userName;
}
public void setUserName(String userName){
// first set the value to this class (component)
this.userName=userName;
//second save this value in the properties file
//a specific method you have to implement
saveproperties("conf.username",userName);
}
/*
* Do like this for all your getters and setters
*/
}
Then, in any time you need to get or save properties, just inject this component and use its getters and setters
#Autowired
ConfigurationManagerComponent configComponent;
String myActualUserName=configComponent.getUserName();
So then you can get all your data in your controller from config component and set them to your spring model to fill form in webpage, and when saving after edit, you can always use setters of your config component(update class and properties file).
This method is not a standard, just a solution we employed to resolve a problem, it's giving good results right now.
You can also check Apache commons configuration Here for other solutions..
Hope this will help.
I am very much new to web services. I have exposed some REST services using Jersey 2 in integration with Spring. Now I need to secure those rest services using authentication with username/password. I am told not to use Spring Security.
I have no idea of how to do this. I did search on the net but various links show various implementation and I am unable to decide how to proceed with it.
A common way for authenticating with username and password is to use Basic Authentication. Basically the client needs to send a request header Authorization, with the the header value as Basic Base64Encoded(username:password). So is my username is peeskillet and my password is pass, I, as a client, should set the header as
Authorization: Basic cGVlc2tpbGxldDpwYXNz
In a servlet environment, the container should have support for Basic authentication. You would configure this support on the web.xml. You can see an example in 48.2 Securing Web Applications of the Java EE tutorial. You will also notice in an example
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
That is for SSL support. This is recommended for Basic Authentication.
If you don't want to deal with the hassle of working with security domains and login modules, realm, and such, that would be required to customize the servlet support, or if you're just not in a servlet environment, implementing Basic Auth in a ContainerRequestFilter is really not too difficult.
You can see a complete example of how this could be done at jersey/examples/https-clientserver-grizzly. You should focus on the SecurityFilter
The basic flow in the filter goes something like this
Get the Authorization header. If it doesn't exist, throw an AuthenticationException. In which case the AuthenticationExceptionMapper will send out the header "WWW-Authenticate", "Basic realm=\"" + e.getRealm() + "\", which is part of the Basic Auth protocol
Once we have the header, we parse it just to get the Base64 encoded username:password. Then we decode it, then split it, then separate the user name and password. If any of this process fails, again throw the WebApplicationException that maps to a 400 Bad Request.
Check the username and password. The example source code just checks if the username is user and the password is password, but you will want to use some service in the filter to verify this information. If either of these fail, throw an AuthenticationException
If all goes well, a User is created from the authenticate method, and is injected into an Authorizer (which is a SecurityContext). In JAX-RS, the SecurityContext is normally used for authorization`.
For the authorization, if you want to secure certain areas for certain resources, you can use the #RolesAllowed annotation for your classes or methods. Jersey has support for this annotation, by registering the RolesAllowedDynamicFeature.
What happens under the hood is that the SecurityContext will be obtained from the request. With the example I linked to, you can see the Authorizer, it has an overridden method isUserInRole. This method will be called to check against the value(s) in #RolesAllowed({"ADMIN"}). So when you create the SecurityContext, you should make sure to include on the overridden method, the roles of the user.
For testing, you can simply use a browser. If everything is set up correctly, when you try and access the resource, you should see (in Firefox) a dialog as seen in this post. If you use cURL, you could do
C:/>curl -v -u username:password http://localhost:8080/blah/resource
This will send out a Basic Authenticated request. Because of the -v switch, you should see all the headers involved. If you just want to test with the client API, you can see here how to set it up. In any of the three cases mentioned, the Base64 encoding will be done for you, so you don't have to worry about it.
As for the SSL, you should look into the documentation of your container for information about how to set it up.
So this is really a matter what you would like to achieve. My case was to get this thing running with mobile and a One-Page-App JavaScript.
Basically all you need to do is generate some kind of header that value that will be needed in every consecutive request you client will make.
So you do a endpoint in which you wait for a post with user/password:
#Path("/login")
public class AuthenticationResource {
#POST
#Consumes("application/json")
public Response authenticate(Credentials credential) {
boolean canBeLoggedIn = (...check in your DB or anywher you need to)
if (canBeLoggedIn) {
UUID uuid = UUID.randomUUID();
Token token = new Token();
token.setToken(uuid.toString());
//save your token with associated with user
(...)
return Response.ok(token).type(MediaType.APPLICATION_JSON_TYPE).build();
} else {
return Response.status(Response.Status.UNAUTHORIZED).build();
}
}
}
Now you need to secure resource with need for that token:
#Path("/payment")
#AuthorizedWithToken
public class Payments {
#GET
#Produces("application/json")
public Response sync() {
(...)
}
}
Notice the #AuthorizedWithToken annotation. This annotaation you can create on your own using special meta annotation #NameBinding
#NameBinding
#Target({ElementType.METHOD, ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
public #interface AuthorizedWithToken {}
And now for the filter that implements checking of the header:
#AuthorizedWithToken
#Provider
public class XAuthTokenFilter implements ContainerRequestFilter {
private static String X_Auth_Token = "X-Auth-Token";
#Override
public void filter(ContainerRequestContext crc) throws IOException {
String headerValue = crc.getHeaderString(X_Auth_Token);
if (headerValue == null) {
crc.abortWith(Response.status(Response.Status.FORBIDDEN).entity("Missing " + X_Auth_Token + " value").build());
return;
}
if(! TOKEN_FOUND_IN_DB) {
crc.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Wrong " + X_Auth_Token + " value").build());
return;
}
}
}
You can create any number of your own annotations checking for various things in the http request and mix them. However you need to pay attention to Priorities but that actually easy thing to find. This method needs using https but that is obvious.
Security comes in two main flavours :
Container Based
application based
the standard way to secure spring applications is to use Spring Security (formerly Acegi).
It would be interesting to know why you're not being allowed to use that.
You could use container based security, but I'm guessing that your use of spring precludes that option too.
Since the choice of Spring is usually to obviate the need for the use of a full J2EE container (Edit : though as pointed out below by others, most ordinary servlet containers do allow you to implement various container based security methods)
This really only leaves you with one option which is to roll your own security.
Your use of Jersey suggests that this might be a REST application.
In which case you really ought to stick with standard HTTP Authentication methods that
comes in the following flavours in reverse order of strength :
BASIC
Digest
Form
Certificate
REST applications are usually supposed to be 'stateless', which essentially rules out form based authentication (because you'd require the use of Session)
leaving you with BASIC, Digest and Certificate.
Your next question is, who am I authenticating. If you can expect to know the username AND the password of the user based on what URL they requested (say if it's one set of credentials for all users) then Digest is the best bet since the password is never sent, only a hash.
If you cannot know the Password (because you ask a third party system to validate it etc.) then you are stuck with BASIC.
But you can enhance the security of BASIC by using SSL, or better yet, combining BASIC with client certificate authentication.
In fact BASIC authentication over HTTPS is the standard technique for securing most REST applications.
You can easily implement a Servlet Filter that looks for the Authentication Header and validates the credentials yourself.
There are many examples of such filters, it's a single self contained class file.
If no credentials are found the filter returns 401 passing a prompt for basic auth in the response headers.
If the credentials are invalid you return 403.
App security is almost an entire career in itself, but I hope this helps.
As the former posts say, you could go with different options, with a varying overhead for implementation. From a practical view, if you're going to start with this and are looking for a comfortable way for a simple implementation, I'd recommend container-based option using BASIC authentication.
If you use tomcat, you can setup a realm, which is relatively simple to implement. You could use JDBCRealm, which gets you a user and password from specified columns in your database, and configure it via server.xml and web.xml.
This will prompt you for credentials automatically, everytime you are trying to access your application. You don't have any application-side implementation to do for that.
What I can tell you now is that you already did most of the 'dirty' job integrating Jersey with Spring. I recommend to you to go an Application-based solution, is it does not tie you to a particular container. Spring Security can be intimidating at first, but then when you tame the beast, you see it was actually a friendly puppy.
The fact is that Spring Security is hugely customizable, just by implementing their interfaces. And there is a lot of documentation and support. Plus, you already have a Spring based application.
As all you seek is guidance, I can provide you with some tutorials. You can take advantage from this blog.
http://www.baeldung.com/rest-with-spring-series/
http://www.baeldung.com/2011/10/31/securing-a-restful-web-service-with-spring-security-3-1-part-3/
I have a controller (Spring Controller) that will serve json to a mobile app.
Various servers run our software. Not all will be configured to serve mobile requests.
I've added a bean of class Integer with the id of an object containing various system parameters necessary to handle requests.
This bean is defined in xml and autowired into the controller.
The autowiring uses (required = false) so we can run without a value defined in xml.
I have checked and found that the autowired Integer is indeed null if not defined in xml.
What I would like to do now is add to my requestmappings in a way that will match one method if that Integer is null and the regular method when the Integer is not null (basically, we'll reply with a standard json error object).
This seems like it'd be pretty straightforward with some sort of AOP, but I've little experience aside from using Spring. Most conditional info in the Requestmapping annotation seems to be based on request parameters, not server-side variables.
Any ideas?
I think that is better use a property-placeholder to load a properties file from the classpath. In this way you can deploy the same war file in different servers and use a different property file for each server (putting it in the AS classpath).
Once you did it you can use a variable in your controller (or in an interceptor if you want to leave the controller's code clean) and do something like this:
#Controller
public class MyController{
#Value("${mobile.enabled}")
private boolean mobileEnabled;
#RequestMapping("/mobile")
public Object json(){
if (!mobileEnabled)
throw new IllegalStateException("This server can't do it!");
}
//create the json
return result;
}
And a properties file like:
mobile.enabled=true
when you want to enable it, or false when don't.
I am designing a REST API that I would like to be localizable in the future.
Therefore I am defining the URLs to be of the form
/en/<resource_url>
With the intention of being able to support
/fr/<resource_url>
In the future if need be.
However I only want to define each resource url service once. Therefore I figure I need to get the URL parsed and rewritten without the language piece of the URL before it is matched to services. Finally that language should be made available to the services somehow for them to localize if necessary.
How can I achieve this?
I am using Jersey 1.17 inside Jetty container embedded in a larger server process.
You can make the /en/ or the /fr/ part a variable. Then set your locale to the value of the variable. Here's an example:
#Path("/{locale}/username")
public class UserResource {
#GET
#Produces("text/xml")
public String getUser(#PathParam("locale") String locale) {
...
}
}
But that may not be the best way to go about it. After answering, I found this other SO question that is a better way to solve the problem: Getting the client locale in a jersey request With this way, you don't need to add this to the URL. Just make the client set a header.