I'm currently developing a Struts 2 web application that allow anonymous usage. I want that with anonymous user, the URL will be like:
http://localhost:8080/myapp
But after user logged in, the URL will be personalized base on user name, for example:
http://localhost:8080/myapp/Cuong-Doan
Please suggest me a plugin/technique that can help me to achieve it.
You can try to do it with Tuckey's UrlRewriteFilter. After loging add session attribute, for example loggedUsername=Cuong-Doan. Then analyze this attribute in UrlRewriteFilter rule using session-attribute parameter of condition element. If it is present -> do redirect, add it to the URL using backreferences.
Personalized could be done via setting the parameter specifying the persona. Looking at the URLs in the question I decided to give you imagination about technique used to reproduce SEO optimized URLs. This technique is called "Parameters after action names". For example to map your persona with the action you can use
#Action(value = "/*", params = {"person", "{1}"})
so, after that action is mapped you will get the information about person via the person parameter that could be used in the action.
Related
I'm a newbie in Liferay and I'm creating a hook to authenticate using a expando column instead of an email address.
My authentication class works fine, but one problem still remains:
After a successful authentication, I must redirect the page to the user's public or private page (any of theese is enough for me)
I followed the common of instructions for this on any forum on Internet:
Create a class that extends com.liferay.portal.kernel.events.Action and do the logic there. In my case, my class is named CustomPostLoginAction
Modify portal.properties adding the entries
login.events.post=com.liferay.sample.hook.action.CustomPostLoginAction
auth.forward.by.last.path=true
default.landing.page.path=/web/guest/home
Redeploy and "voilá"
When I reboot my web server, everything is fine, but when I run my hook using any browser, once I get successfully authenticated, it stills showing me the default login error messages. When I check my console, I found that my action class is never called and no special action is executed after my authentication class. So I have the following questions:
Where can I found an example to class to be used as a value for the property "auth.pipeline.post" if needed?
On the method authenticateByEmailAddress on my authentication class, the last argument is a java.util.Map containing parameters like "doActionAfterLogin", "redirect", "structsAction", etc. Do I get something if I assign values to those keys on that map? If yes, where can I found an example of valid values to assign to each one of them?
Do I have to change something in my custom login page? (it works, but still I have to ask this)
Is it necessary to work with the class DefaultLandingPageAction? If yes, how can I do it? Because I have only the portal's bytecodes (.class)
And most important: What am I doing wrong?
For the record:
I'm using Liferay 6.1 bundle with Tomcat 7 and SDK included with Liferay's default database.
If any of you need to watch any of my source code and/or properties files, just let me know and I will publish them.
Thanks in advance to all of you.
I can't add a comment to your original post so I'm gonna have to post an answer to ask you for some additional information (will update my answer accordingly).
Did you modify portal.properties directly or did you create a new portal.properties inside your hook?
Once you extended com.liferay.portal.kernel.events.Action, did you override the run method?
Does anybody have a quick method to generate slugs and permalinks in Grails 1.3.7/2.0.0.RC1?
The main restriction: this method should work with non-latin characters.
Russian/bulgarian cirillic, deutsch umlauts etc...
Any suggestions ?
Grails 2.0.0.RC1
From the 2.0.0.RC1 docs:
Link Generation API
A general purpose LinkGenerator class is now available that is usable
anywhere within a Grails application and not just within the context
of a controller. For example if you need to generate links in a
service or an asynchronous background job outside the scope of a
request:
LinkGenerator grailsLinkGenerator
def generateLink() { grailsLinkGenerator.link(controller:"book", action:"list") }
Although it's not stated explicitly, I assume the reference to grailsLinkGenerator is obtained via dependency injection
Grails 1.3.7
You can use either the createLink or resource tags to generate links. If you're generating permalinks, I assume you'll want these to be absolute URLs. If so, you'll need to use either the absolute or base attribute when using these tags.
If you use the absolute attribute, be sure to set the value of grails.serverURL in Config.groovy
Link Permanence
The text above describes how to generate links to resources in a Grails application, but doesn't say anything about how to make these links permanent. AFAIK, the link to a resource will always remain the same as long as you don't change anything that is used in the URL mapping scheme (as defined in UrlMappings.groovy)
By default the URL mapping scheme uses
the resource's ID
the controller name
the action name
So if you never change these for the links of interest, you should be good.
As easy as:
title.replaceAll("[\\W]+", "-")
That makes it.
I believe it has something to do with Struts2 ValueStack, but if you guys could give me a hand with that would be great.
I have the following setup: Spring 3 + Struts 2.
My struts actions are pretty much like this:
#ParentPackage("struts-default")
public class StepOneAction extends ActionSupport {
...
}
Such Action has a method that is my forward:
#Action(value = "/bla", results = { #Result(name = "ble", location = "/bli.jsp") })
public String populate() {
...
return BLE;
}
Finally such Action is #Autowired.
What's puzzling me is that if I open, say Firefox, navigate to the first page - it's a 3 step wizard - fill the form and submit THEN open another browser, say Opera, and navigate to the first page, Opera has the data populated from Firefox.
How's that possible? What am I missing?
The ValueStack is per-request, so I don't see how it could possibly be a factor here.
It sounds like Spring is treating StepOneAction as a singleton, which would account for the behavior you are seeing. Actions need to be instantiated per-request.
Check that you haven't defined a member on the JSP page or Servlet that keep the same value among multiple sessions
I'm trying to make a simple forum just to get the hang of the Spring Security and MVC frameworks.
For simplicity's sake, let's I have a JSP to view a forum post, which looks like the following:
<body>
...
Title: ${forumPost.title} <br>
Author: ${forumPost.author.name} <br>
Message: {forumPost.message} <br>
<security:authorize ifAnyGranted="ROLE_ADMIN">
Edit: Edit
</security:authorize>
...
</body>
My problem is: not only should an Administrator be able to edit this post, but the original author should be able to as well. Therefore, I only want ROLE_ADMIN and the original author to be able to see the Edit link. However I'm not sure how to filter by user with the security:authorize tag, or if I'll need to go about this a different way.
Any suggestions would be much appreciated. Thanks!
Assuming that you have a controller that sits behind this page, I would simply add a canEditPost field to the ModelAndView that looks something like (semi-pseudocode):
private boolean isAdmin() {
Authentication currentAuthObj = SecurityContextHolder.getContext().getAuthentication();
List<GrantedAuthority> authorities = Arrays.asList(currentAuthObj.getAuthorites());
for (GrantedAuthority auth : authorities) {
if ("ROLE_ADMIN".equals(auth.getAuthority())) {
return true;
}
}
return false;
}
boolean currentUserIsAuthor = ...;
modelAndView.addObject("canEditPost",
Boolean.valueOf(currentUserIsAuthor || isAdmin());
And then in your view just reference $canEditPost.
It's generally better for the view to just reference a simple flag in the model than have the view/template doing the actual logic.
Does your Author object implement equals in such a way that each author is unique?
If so, you could simply check if the Author is the same as the current user (You'd have two sets of tags).
you can have conditions
<% if(mycondition.isTrue()){ %>
<security:authorize ifAnyGranted="ROLE_ADMIN">
Edit: Edit
</security:author
<% }%>
#matt b's answer is a great way to do it and is probably what I'll end up doing. But I found another way that is a bit more complicated but will achieve what I put in this post.
I did a bit of reading and found out that you can handle security at the domain object level and essentially give read/write/delete privileges to a role or to an arbitrary object, for example, the current user ID. In this example, I would give the current user id access to a domain object, in this case a ForumPost object that has its own unique id from the database.
The current user id would then be granted read and write access, which can (via the XML configuration) be defined as a custom role of sorts (I believe the correct term is actually Voter). I could then name this voter MESSAGE__EDIT.
So, in my JSP I could then use the following:
security:authorize ifAnyGranted="MESSAGE_EDIT"
And it would (again, through XML configuration) get the current user id and give access based on the current domain object, in this case, a ForumPost object.
It is a fair bit more work than it sounds, but it can definitely be done.
Some documentation on all this can be found in the Domain Object Security section in the Spring Security Reference Documentation (http://static.springframework.org/spring-security/site/reference/html/springsecurity.html (for some reason the link to the Domain object Security section is broken for now)).
I have a wicket web application with Page mounted to bookmarkable alias. The page contains a form object with submit action.
The problem is that though the form belongs to the page the action url doesn't contain page alias, but rather created in cryptic form of wicket action.
Is there a way to adjust that behavior, so link will be like page_alias/submit ?
...
setRenderStrategy(IRequestCycleSettings.ONE_PASS_RENDER);
mountBookmarkablePage("/resetpwd", ResetPasswordPage.class);
...
public ResetPasswordPage(final String id, final PageParameters parameters) {
final Form form = new StatelessForm();
form.add(new Button("submit") {
public void onSubmit() {
...
});
add(form);
If you subclass StatelessForm instead of Form, this will take you part of the way. Rather than having something like
action="myapp/?wicket:interface=:1:eventEditor::IFormSubmitListener::"
with the page containing the form mounted at a bookmarkable URL, you'll get something like, for example,
action="myapp/mount/path/some/params/?wicket:interface=:0:eventEditor::IFormSubmitListener::"
This uses a MixedParamUrlCodingStrategy for the mount in WebApplication.init()
You can then override encodeUrlInHiddenFields() to return true, which will give you a clean URL in the action attribute.
However, all this doesn't really change the way Wicket works with forms, i. e., you still have some Wicket-specific state data in the client's markup. The reason why this is so hard, I believe, is that Wicket is meant to help you build a web app that has state. I noticed that Wicket does a lot of stuff (like comparing submitted form values with what the model's getters return before the setters are called) behind the scenes, that I know too little about to be comfortable when just cutting it out.
You can use Wicket to provide RESTful web services, though, as outlined in this blog post. There's also a project on Google code called wicket-rest that expands on this idea. Note that this seems to work as simple as it does because it just never uses the whole component based UI building stuff.
The guy who wrote this post had a different problem, but it helped me understand Wicket forms a little better anyway.
you can hide a lot of the request mumbo jumbo by using a HybridUrlCodingStrategy like so:
mount(new HybridUrlCodingStrategy("/resetpwd", ResetPasswordPage.class));
Then when the click submit, assuming you don't redirect to a new page, the url would change from
mysite.com/DocRoot/resetpwd
to
mysite.com/DocRoot/resetpwd.1
or if you really want it to be mysite.com/DocRoot/resetpwd/submit you could create a new bookmarkable page, say ResetPasswordResult.class, set your response page to that and mount it at "/resetpwd/submit"
You might look at other encoding strategies to see if their is another that suits you better:
http://cwiki.apache.org/WICKET/url-coding-strategies.html
You can take a look at http://day-to-day-stuff.blogspot.com/2008/10/wicket-extreme-consistent-urls.html and try to adapt that for Forms.