Annotation Based Security:
1.) Create an enum class to define the roles:
public enum Role {
USER, SUPP, ADMIN;
}
2.) Create an annotation interface which will accept the
role and actions:
import
java.lang.annotation.ElementType;
import
java.lang.annotation.Inherited;
import
java.lang.annotation.Retention;
import
java.lang.annotation.RetentionPolicy;
import
java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface Authorization {
Role
role();
AuthActions[]
actions();
public enum AuthActions{
READ,WRITE;
}
}
3.) Create an annotation interface which will
accept the authorization values:
import
java.lang.annotation.ElementType;
import
java.lang.annotation.Inherited;
import
java.lang.annotation.Retention;
import
java.lang.annotation.RetentionPolicy;
import
java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface Authorizations {
Authorization[] values();
}
4.) Create annotation interface for write
authorization:
import
java.lang.annotation.ElementType;
import
java.lang.annotation.Inherited;
import
java.lang.annotation.Retention;
import
java.lang.annotation.RetentionPolicy;
import
java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface WriteAuthorization {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface WriteAuthorization {
}
5.) Create sample VO class which will accept the user credentials :
import
java.io.Serializable;
public class User implements Serializable{
private static final long serialVersionUID = 1L;
private String userId;
private String userName;
public String
getUserId() {
return userId;
}
public void
setUserId(String userId) {
this.userId = userId;
}
public String
getUserName() {
return userName;
}
public void
setUserName(String userName) {
this.userName = userName;
}
}
6.) Create a class which store the user details and
his roles, this class will be used by filter:
import
java.io.Serializable;
import
java.util.ArrayList;
import
java.util.Collections;
import java.util.List;
public class TestUser implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private final
List<Role> roles;
private final User user;
public TestUser(final
List<String> inRoles, final User inUser) {
final
ArrayList<Role> tmpRoles = new ArrayList<Role>();
if (inRoles != null) {
for (String name :
inRoles) {
for (Role userRole
: Role.values()) {
if
(name.equals(userRole.name())) {
tmpRoles.add(userRole);
}
}
}
}
roles = Collections.unmodifiableList(tmpRoles);
user = inUser;
}
public final boolean hasRole(final Role inRole) {
for (Role role : roles) {
if (role ==
inRole) {
return true;
}
}
return false;
}
public
List<Role> getRoles() {
return roles;
}
public User getUser()
{
return user;
}
}
ThreadLocal:
7.) Create UserSession class, here we need to save
the user and roles in ThreadLocal:
import java.util.List;
public class UserSession {
private static final
ThreadLocal<User> currentUser=new ThreadLocal<User>();
private static final
ThreadLocal<List<String>> roles=new
ThreadLocal<List<String>>();
public static User
getCurrentuser() {
return currentUser.get();
}
public static
List<String> getRoles() {
return roles.get();
}
public static void
setCurrentUser(User user, List<String> inRoles) {
currentUser.set(user);
roles.set(inRoles);
}
public static void cleanup() {
currentUser.set(null);
roles.set(null);
}
}
8.) Next you’ll need to provide your custom session
class-making it a subclass of AuthenticatedWebSession. This class requires you
to override the following methods:
- authenticate - called when the user needs to be authenticated using a username and password
- getRoles - called after the users was authenticated and should provide the roles associated with the authenticated user.
import
java.util.Locale;
import
org.apache.wicket.Request;
import
org.apache.wicket.authentication.AuthenticatedWebSession;
import
org.apache.wicket.authorization.strategies.role.Roles;
public class TestSession extends
AuthenticatedWebSession{
/**
*
*/
private static final long serialVersionUID = 1L;
private final TestUser user;
public
TestSession(Request request) {
super(request);
user = new
TestUser(UserSession.getRoles(),
UserSession.getCurrentuser());
setLocale(Locale.ENGLISH);
}
public TestUser
getUser() {
return user;
}
@Override
public boolean
authenticate(String userId, String userName) {
return false;
}
@Override
public Roles
getRoles() {
Roles
roles=new Roles();
roles.add("USER");
return roles;
}
}
9.) Create a filter UserFilter .java class
which extends the OncePerRequestFilter. This class should authenticate the
panex user and set user details in UserSession.
final IPanexProfile
profile=(IPanexProfile)securityContext.getProfile();
String
name=profile.getUniqueName ();
String
userId=profile.getUserId ();
List<String> roles = new
ArrayList<String>();
roles.add(Role.ADMIN.name());
roles.add(Role.SUPP.name());
User user=new User();
user.setUserId(userId);
user.setUserName(name);
UserSession.setCurrentUser(user, roles);
10.) Enabling the annotations for role based authorization
is done by setting the WebApplication#getSecuritySettings value to AuthorizationStrategy
class. This class implements the IAuthorizationStrategy and IUnauthorizedComponentInstantiationListener
interfaces.
This class have a method isAuthorized() which will read the
annotation values of each classes and check whether the user have the
permission to access this page.
private boolean isAuthorized(
final Class<? extends Component>
componentClass,
final AuthActions
inRequiredAuth) {
final TestSession
session = (TestSession) TestSession.get();
final TestUser
loginUser = session.getUser();
final Authorizations authorizations
= componentClass
.getAnnotation(Authorizations.class);
if (authorizations
== null) {
return true;
}
else {
final Authorization[] auth =
authorizations.values();
for (Authorization authorization :
auth) {
if
(loginUser.hasRole(authorization.role())) {
for (AuthActions
action : authorization.actions()) {
if (action ==
inRequiredAuth) {
return true;
}
}
}
}
return false;
}
}
To establish authorization and authentication, the
application class must extend AuthenticatedWebApplication. When you create your
class you’ll be asked to override the following methods:
- newSession - return a subclass of AuthenticatedWebSession
- getSignInPageClass - return the class for your login page (this one should not require authentication, otherwise you’ll create an infinite loop)
In init() method of
wicket application we need to set SecuritySettings value to AuthorizationStrategy
class
@Override
protected void init() {
getPageSettings().setAutomaticMultiWindowSupport(true);
getMarkupSettings().setStripWicketTags(true);
final
AuthorizationStrategy authorizationStrategy = new
AuthorizationStrategy();
getSecuritySettings().setAuthorizationStrategy(authorizationStrategy);
getSecuritySettings().setUnauthorizedComponentInstantiationListener(authorizationStrategy);
addComponentInstantiationListener(new
SpringComponentInjector(this));
getResourceSettings().setThrowExceptionOnMissingResource(true);
}
The authorization and role can be given to each page in the
following way
@Authorizations(values = { @Authorization(actions =
{AuthActions.READ}, role = Role.SUPP) })
public
class FirstWicketHome extends
WebPage()
FirstWicketHome page can be viewed only by the user who has
the SUPP roles.
Web.xml :
You have to configure the filter in web.xml :
<filter>
<filter-name>userFilter</filter-name>
<filter-class>test.security.ResourceIgnoringDelegatingFilter</filter-class>
<init-param>
<param-name>DELEGATE_FILTER_CLASS</param-name>
<param-value>test.security.UserFilter</param-value>
</init-param>
</filter><!--
<filter-mapping>
<filter-name>userFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
No comments:
Post a Comment