I am trying to extend the user authentication example, which is also presented here, so that multiple users can login to the server. I would also like to assign a different home directory for each user. So far, I haven't been able to find any such utility provided by the Apache SSHD API, so I have tried the following workaround, by using the utilities provided by the Apache FtpServer.
What I attempt to do is:
create a UserManager object to manage a list of users and store their information in a property file, in a way similar to this example
create a PasswordAuthenticator that makes use of the UserManager in its authenticate method, as follows:
public class MyPasswordAuthenticator implements PasswordAuthenticator {
private UserManager userManager;
public MyPasswordAuthenticator(){
this.userManager=null;
}
public MyPasswordAuthenticator(UserManager manager) {
this.userManager=manager;
}
#Override
public boolean authenticate(String username, String password, ServerSession session) throws PasswordChangeRequiredException {
if (this.userManager==null) return false;
User usr=null;
try {
usr = userManager.getUserByName(username);
} catch (FtpException e) {
e.printStackTrace();
}
if (usr==null) return false;
else{
String pass=usr.getPassword();
return password.equals(pass);
}
}
}
However, the usr.getPassword() returns null, even though a) the password fields in the property file do have values b) I have checked the functions getName() and getHomeDirectory() and they return their respective String values.
My question is, why does this happen and what should be done to fix this?
I have found a way to make it work, it is:
usr = this.userManager.authenticate(new UsernamePasswordAuthentication(username, password));
Related
I'm trying to do logging for different user roles (admin, developers, end users, etc.), and I want to show a different/filtered log for end-users. How can I achieve that?
How can I approach this problem?
You could probably tackle this problem with using something like a ThreadLocal variable in your logging filter. That is set by the code that does the authentication. And based on that do your different logging.
A simple example, in your filter class you could have something like this:
private static final ThreadLocal<String> ROLE = new ThreadLocal<>();
public void doTheFiltering() {
String role = ROLE.get();
if (role == null) {
// not authenticated...
} else if (role.equals("ADMIN") {
// filter based on admin privileges
} else ...
}
public static void setRole(String role) {
ROLE.set(role);
}
public static void clearRole() {
ROLE.remove();
}
And in your authentication code:
try {
String role = ... // find out role
MyFilter.setRole(role);
// continue with whatever you're doing
} finally {
// clean up the role on this thread.
// this is especially needed when you're using a thread pool that handles requests.
MyFilter.clearRole();
}
I have implemented parallel testing using Selenium and TestNG for a web application, however, my webapp got a restriction where only one session can be handled at the time (it is not supporting multi-sessions, when you login with the same user it will disconnect your older session), the solution of which I have thought to solve it is to create a unique user for each test (using API), so I have implemented it but when I am running the tests in parallel (using testng.xml file with thread-count="2") I am creating the same user twice! with the same credentials, I want to be able to create a unique user where it will create one unique user for each run.
This is my code:
public class BaseApiTest extends BaseTest {
protected String token;
protected String CREATED_ADMIN_TEST_USER;
protected String CREATED_ADMIN_TEST_PASSWORD;
private static final AtomicReference<String> ACCESS_TOKEN = new AtomicReference<>();
#BeforeClass(alwaysRun=true)
public void baseApiSetup() throws InterruptedException, ApiException {
generateToken();
createAdminUser();
}
private void generateToken() {
........
..........
...........
token = "Bearer " + ACCESS_TOKEN.get();
context.setAttribute("api-key", token);
context.setAttribute("HOST", HOST);
T_Logger.info("Host url address is: =[{}]", HOST);
T_Logger.info("new api key token =[{}]", token);
}
private void createAdminUser() throws ApiException, InterruptedException {
UsersAPIUnitTest usersAPITU = new UsersAPIUnitTest(context);
usersAPITU.createUser();
CREATED_ADMIN_TEST_USER = UsersAPIUnitTest.getEmail();
CREATED_ADMIN_TEST_PASSWORD = UsersAPIUnitTest.getPassword();
}
}
and this is used by the login page with the newly created user:
protected void adminSignIn() {
loginPage.login(CREATED_ADMIN_TEST_USER, CREATED_ADMIN_TEST_PASSWORD, true);
writeToLoggerSignIn(CREATED_ADMIN_TEST_USER);
}
and then I am starting to run my tests.
Expected: each test class will contain its own unique user
Actual: all the users that are being created are the same user with the same credentials
========================EDIT===============================
This is how I create new user:
public String createUserCms(String name, String email, String phone, String password) throws ApiException {
NewUserPayload body = new NewUserPayload();
body.setStatus(true);
body.setName(name);
body.setEmail(email);
body.setPhone(phone);
body.setPassword(password);
body.setPasswordConfirmation(password);
printBody(body);
return usersApi.createUser(token, body);
}
I have been working on a generic solution for this problem so that all automation teams can use it, still work in progress. I'm sure you would have explored other options, but creating users every time you run a test is not a good idea, rather you have to create the users once and use them otherwise you end up adding more users into your system (if you are cleaning up the users #afterMethod that's fine)
But for now, in your case, you have to make sure that you pass a unique name/email when creating the user and return that username/email address.
If you can share your createUser method snippet, we can help you more.
Suppose, there's a site that provides an API, such as this:
Users post questions, answers on that site
You can make GET and
POST calls
There are two types of authentication: weak (only gives
read rights) and strong (gives both read and write rights)
Right now, I'd like to read users' questions and answers (only need weak access) and send them messages or post my own questions in the future (would need strong access)
The site's API has actions both to do with users (e.g. send a message) and with site in general (see about, see most popular questions)
What I have right now looks like this:
public class Wrapper {
private AccessToken accessToken;
public Wrapper(...) {
//does some stuff
//gets access token:
getAccessToken(...);
}
public AccessToken getAccessToken(...) {
AccessToken result;
//gets access token, given the auth info provided as arguments
accessToken = result;
return result;
}
public ArrayList<Question> getQuestions(User user) {
//gets user's questions, using the accessToken field
//set's a user's questions field to the result and returns the result
}
public ArrayList<Answer> getAnswers(User user) {
//same as previous
}
public boolean sendMessage(User user) {
//sends a message, if current accessToken is strong
}
}
and User class:
class User {
private String username;
private ArrayList<Question> questions;
private ArrayList<Answer> answers;
public User(String username) {this.username=username;}
//getters and setters
}
So, to use it you would use something like this:
public class Main {
public static void main(String[] args) {
Wrapper wrapper = new Wrapper(...);
ArrayList<Question> questions = wrapper.getQuestions(new User("username"));
wrapper.sendMessage(new User("username2"));
}
}
I have issues with this.
First of all, class User feels superfluous, since all the functionality is inside the Wrapper class.
Second, I wonder if what my methods do is wright - from the design's perspective: in getAccessToken I both return AccessToken and set a Wrapper's field accessToken to the result. Is this the right approach? Or should the method only return access token and then that result should be assigned to a class' field explicitly? Same goes for the getQuestions and getAnswers methods: they both get the ArrayLists, return them and assign a User's field to the result - all inside the single method.
I would like for a User class to have some meaning. I thought of doing it something like that:
Wrapper wrapper = new Wrapper(...);
User user = new User("username");
user.getQuestions(wrapper.getAccessToken());
user.sendMessage(wrapper.getAccessToken());
So, the Wrapper class would only serve as a place to get an access token from, which doesn't feel right as well. I could place the access token functionality inside the User class and use it like this:
User user = new User("username", ...);
user.getQuestions();
user.sendMessage();
The User's constructor would take both username and auth data, would get access token and store it inside a user and then use it when getting questions/answers or sending messages. I could make the accessToken field inside User class static so that all users shared the same token.
However, there are actions the site API provides, that aren't obviously connected with users: for instance, getting the site's most popular questions. It feels right to use a generic Wrapper class for that purpose which contradicts with the previous approach.
I'm new to this and only know a couple design patterns. Perhaps, there are widespread patterns that are to be used for this type of problem? Any help/advice is appreciated.
There are a few alternatives that you can do to solve your problem, but there is likely not one that is better than all others. The solution you choose will depend on the trade-offs and how you want your system to operate. The following are two common solutions to this type of problem.
Have the Wrapper generate a User: Instead of generating a User object separate from the Wrapper, you can have the Wrapper generate the User object. This allows the Wrapper to embed the AccessToken within the User without any outside client knowing that a user has an AccessToken. For example, you can use the following Wrapper and User definitions:
public class Wrapper {
public Wrapper(...) {
// ... does some stuff, but DOES NOT get an access token ...
}
private AccessToken getAccessToken(...) {
AccessToken result;
// ... gets access token, given the auth info provided as arguments ...
return result;
}
public User findUser(String username, ...) {
return new User(username, getAccessToken(...));
}
}
class User {
private String username;
private final AccessToken token;
public User(String username, AccessToken token) {
this.user = user;
this.token = token;
}
// ... getters and setters ...
}
Note that getAccessToken is now private, as no other client needs to access this method. All of the methods of Wrapper continue to accept a User argument, but they now should obtain the access token by calling getToken on the User object, rather than using a stored AccessToken in Wrapper.
Also note that the token field is final, since the access token associated with a User should not change over the life of a User object.
Embed the Wrapper in User: This technique is similar to (1), but it also embeds the Wrapper object in the User object. This allows the User class to act as a live object, which can be queried for questions and answers and can be used to send messages. Since all of the methods of Wrapper accept a User argument, this is a good sign that the methods should be moved to User. The following is a halfway point to refactor the Wrapper methods into User:
public class Wrapper {
public Wrapper(...) {
// ... does some stuff, but DOES NOT get an access token ...
}
private AccessToken getAccessToken(...) {
AccessToken result;
// ... gets access token, given the auth info provided as arguments ...
return result;
}
public User findUser(String username, ...) {
return new User(username, getAccessToken(...));
}
public ArrayList<Question> getQuestions(User user) {
//gets user's questions, using the accessToken field
//set's a user's questions field to the result and returns the result
}
public ArrayList<Answer> getAnswers(User user) {
//same as previous
}
public boolean sendMessage(User user) {
//sends a message, if current accessToken is strong
}
}
class User {
private String username;
private final AccessToken token;
private final Wrapper wrapper;
public User(String username, AccessToken token, Wrapper wrapper) {
this.user = user;
this.token = token;
this.wrapper = wrapper;
}
public List<Question> findQuestions() {
return wrapper.getQuestions(this);
}
public ArrayList<Answer> findAnswers() {
return wrapper.getAnswers(this);
}
public boolean sendMessage() {
return wrapper.sendMessage(this);
}
// ... getters and setters ...
}
Using this technique, clients can now directly get questions and answers from a User object. Note that the findQuestions and findAnswers methods start with find. This tips off clients that this call may be a long call (as opposed to getQuestions or getAnswers, which would make a client assume that it is a simple getter and the method would return nearly-instantly). The fact that these methods execute a remote call should also be documented in the Java-docs for the methods. If the call takes a long time, the methods should return a Future (or a similar object) and be made asynchronously.
If you want to go all-in on the refactor, you can move all of the implementation details from the Wrapper class to the User class:
public class Wrapper {
public Wrapper(...) {
// ... does some stuff, but DOES NOT get an access token ...
}
private AccessToken getAccessToken(...) {
AccessToken result;
// ... gets access token, given the auth info provided as arguments ...
return result;
}
public User findUser(String username, ...) {
return new User(username, getAccessToken(...));
}
}
class User {
private String username;
private final AccessToken token;
private final Wrapper wrapper;
public User(String username, AccessToken token, Wrapper wrapper) {
this.user = user;
this.token = token;
this.wrapper = wrapper;
}
public List<Question> findQuestions() {
// ... find the questions remotely ...
}
public ArrayList<Answer> findAnswers() {
// ... find the answers remotely ...
}
public boolean sendMessage() {
// ... send message remotely ...
}
// ... getters and setters ...
}
This may not be the best approach, as it may be a better idea to keep the details of accessing the remote API abstracted in the Wrapper class. This is a judgment call that will depend on the nature of your specific application.
There are numerous other techniques that you can do, but the above two are common approaches to the problem you are trying to solve.
I'm using Java Mail API:
PasswordAuthentication valid = new PasswordAuthentication(txtEmail.getText(),
txtPassword.getText());
if (valid != null) {
lblInvalid.setText("Correct information!");
} else {
lblInvalid.setText("Invalid username or password!");
}
What I want it to do, I want the user to login with their gmail username and password. I want to check if that email username and password is the real gmail login information. How do I check if the email and password enters is the users gmail account.
In Java, doing new Anything() will NEVER return null.
Also, this class seems to only be a placeholder data structure, used by other parts of the JDK. It does not intrinsically do validation.
Validating an email address is usually done with regex, and kept simple. You should then send the user a confirmation message to verify their email address if that's important to you.
Passwords can also be validated for correct form using regex.
Update
Looking more closely at the error messages you are trying to emit, it looks like you want to handle authentication yourself. There are tons of ways to do this but a very simple prototype-only solutions is something like:
// create a static mapping of user/passwords:
private static Map<String, String> logins = new HashMap<String, String>();
Then in your handler:
if (txtPassword.getText().equals(logins.get(txtEmail.getText()))) {
lblInvalid.setText("Correct information!");
} else {
lblInvalid.setText("Invalid username or password!");
}
For something you're going to use in production I'd highly recommend Spring Security.
To validate email address you can refer this link
http://www.mkyong.com/regular-expressions/how-to-validate-email-address-with-regular-expression/
For validating password: You just need to retrieve the stored password for a user from some database or other security frameworks and validate against the input done by the user.
This is a pretty large topic.
Authentication, Authorization and validation are three different things (but pretty much related).
If you are a beginner and you are just trying some mock authentication with hard-coded credentials you could improve a little on your code with something like this:
public class Authenticator {
public boolean authenticateWithCredentials(String email, String password) {
boolean areValidCredentials = false;
//Validate credentials here with database or hardcoded
if(email.equals("my_email#emailprovider.com") && password.equals("mypassword")) {
areValidCredentials = true;
}
return areValidCredentials;
}
}
if you are going to use just one instance of this class you might use the Singleton pattern:
public class Authenticator {
//Singleton pattern
private static Authenticator instance;
public static Authenticator getInstance() {
if(instance == null) {
instance = new Authenticator();
}
return instance;
}
private Authenticator() {
//Block creation of Authenticator instances
}
public boolean authenticateWithCredentials(String email, String password) {
boolean areValidCredentials = false;
//Validate credentials here with database or hardcoded
if(email.equals("my_email#emailprovider.com") && password.equals("mypassword")) {
areValidCredentials = true;
}
return areValidCredentials;
}
}
I want to login my users automatically from our application. I know liferay has an auto login feature, but I don't know how to use it. I didn't find much valuable information on the web.
What do I need to do to make autologin work?
I want to login a user automaticaly when he clicks a link, without him having to enter name and password. The name and password is saved on our application database.
I believe the OP has no use for an answer now. Nonetheless, this deserves a comprehensive answer. In fact, I am surprised that it does not have one yet.
First of all, this is a bad idea: such an arrangement as the one proposed by the OP is really too insecure. Nevertheless, a solution to the described problem can be a good prototype for someone creating an autologin for Liferay.
Now, let us say you want to automatically log in any user whose screen name is sent in a query string parameter. For example, if one access http://localhost:8080/web/guest/home?insecurely_login_user=juju then the Liferay in the juju user should be logged in. How to do that? Follow the steps below:
Create the autologin class
Firstly, create a hook plugin. In its docroot/WEB-INF/src directory, creates a class implementing the com.liferay.portal.security.auth.AutoLogin interface. In my example, I will call it br.brandizzi.adam.liferay.insecure.InsecureAutoLogin.
The AutoLogin interface has only one method, called login(), which expects two parameters (an HttpServletRequest and an HttpServletResponse instances) and returns an array of strings. So, my class will look like this without implementation:
public class InsecureAutoLogin implements AutoLogin {
#Override
public String[] login(HttpServletRequest request,
HttpServletResponse response) throws AutoLoginException {
// TODO Auto-generated method stub
return null;
}
}
The AutoLogin.login() method will try to retrieve the information necessary to the authentication from many sources, mainly the request object. If it decides that the user should be logged in, it returns an array with relevant data for authentication; if it decides to not log the user in, it can just return null.
In our case, we try to get the name of the user from the the insecurely_login_user parameter from the request. If there is such parameter, we will proceed with the login; if there is no such parameter, it just returns null:
String screenName = request.getParameter("insecurely_login_user");
if (screenName == null || screenName.isEmpty()) {
return null;
}
So we have the screen name. What to do now? Let us get a user from the database with the same screen name.
long companyId = PortalUtil.getCompanyId(request);
User user = UserLocalServiceUtil.getUserByScreenName(companyId,
screenName);
If a user wich such a screen name exists, it will be retrieved and attributed to the user variable. In this case, the authentication should be successful and the autologin class should return an array of three strings - the credentials. Those are the values to be returned as credentials, in the order they should appear in the array:
the user id as a string
the password of the user, which can be encrypted or not;
a boolean value, cast to string, indicating if the password is encrypted.
So here is the line:
return new String[] {
String.valueOf(user.getUserId()),
user.getPassword(),
String.valueOf(user.isPasswordEncrypted())
};
If a user is not found, however, an exception will be thrown. So, we have to surround the code above with a try/catch construction. If an exception is thrown, just return null:
try {
long companyId = PortalUtil.getCompanyId(request);
User user = UserLocalServiceUtil.getUserByScreenName(companyId,
screenName);
return new String[] { String.valueOf(user.getUserId()),
user.getPassword(),
String.valueOf(user.isPasswordEncrypted()) };
} catch (Exception e) {
return null;
}
In the end, this is my InsecureAutoLogin class:
public class InsecureAutoLogin implements AutoLogin {
public String[] login(HttpServletRequest request,
HttpServletResponse response) throws AutoLoginException {
String screenName = request.getParameter("insecurely_login_user");
if (screenName == null || screenName.isEmpty())
return null;
try {
long companyId = PortalUtil.getCompanyId(request);
User user = UserLocalServiceUtil.getUserByScreenName(companyId,
screenName);
return new String[] { String.valueOf(user.getUserId()),
user.getPassword(),
String.valueOf(user.isPasswordEncrypted()) };
} catch (Exception e) {
return null;
}
}
}
Registering the autologin class
Now our hook should register this class as an autologin processor. That is really easy.
First, edit the file docroot/WEB-INF/liferay-hook.xml adding a portal-properties element with the value portal.properties:
<?xml version="1.0"?>
<!DOCTYPE hook PUBLIC "-//Liferay//DTD Hook 6.1.0//EN" "http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd">
<hook>
<portal-properties>portal.properties</portal-properties>
</hook>
Now, create a file named portal.properties at docroot/WEB-INF/src. It should contain a property named auto.login.hooks whose value should be the name of our class:
auto.login.hooks=br.brandizzi.adam.liferay.insecure.InsecureAutoLogin
And that is it. Deploy this hook and your autologin will work.
Conclusion
As I have said, you should not use such an unsafe "authentication" method. It is too easy to bypass it, getting even administration permissions! However, if you follow these steps, you have a skeleton to create a better autologin feature. Also, I know some people really want to do something like this insecure "authentication" method and sometimes we have to suspend our judgments and just help one to shoot one's feet...
The source code of this project can be found here and you can download the WAR here.
Step 1: Create a class CustomLoginFilter and implements from AutoLogin interface.Override login method. Code as follows.
public String[] login(HttpServletRequest req, HttpServletResponse response)throws AutoLoginException {
//Get the login parameter
String loginEmailId = ParamUtil.getString(req, “_58_login”);
String password = req.getParameter(“_58_password”);
String[] credentials = new String[3];
credentials[0] = userId
credentials[1] = loginEmailId;
credentials[2] = password;
//Write your business logic Here and return String[].
}
Step 2: Write below code in portal-ext.properties
// you get full control from this custom class.
auto.login.hooks=com.bolog.portal.login.security.CustomLoginFilter
//Override Liferay Authentication pipeline
auth.pipeline.enable.liferay.check=false
auth.pipeline.pre=com.bolog.portal.login.security.CustomLoginAuthenticator
Step 3: Create class CustomLoginAuthenticator and implements from Authenticator.
Override authentication methods.
public int authenticateByEmailAddress(long arg0, String arg1, String arg2,
Map<String, String[]> arg3, Map<String, String[]> arg4)
throws AuthException {
//Write Your business login here and if authentication success then return 1 otherwise return 0;
return 0;
}
public int authenticateByScreenName(long arg0, String arg1, String arg2,
Map<String, String[]> arg3, Map<String, String[]> arg4)
throws AuthException {
//Write Your business login here and if authentication success then return 1 otherwise return 0;
return 0;
}
public int authenticateByUserId(long arg0, long arg1, String arg2,
Map<String, String[]> arg3, Map<String, String[]> arg4)
throws AuthException {
//Write Your business login here and if authentication success then return 1 otherwise return 0;
return 0;
}
Step 4: If authentication fail then you can also redirect any page by following code
if(Validator.isNull(credentials) || credentials[0]==null){
req.setAttribute(AutoLogin.AUTO_LOGIN_REDIRECT, “Your Login page path”);
}
What exactly do you mean by "autologin"? If you want Liferay to check wheter the user is already authenticated by some external entity (like a single sign-on server as CAS), you can just enable that in the portal.properties. There it's already preconfigured for the liferay supported authentication mechanisms. Otherwise you might need to implement your own autologin hook (as indicated in this post for example
Well found it.
Step 1: Click on add iframe and let the configuration view pop up.
Step 2: Provide the url and if there are any variables like (www.mysite.com/Action=Login&User . . . .), add the Action=Login in hidden variables text field.
Step 3: Click authenticate and select form based authentication. In this, make usre that the user field name and password field name are given correctly, and the values will be '#screen_name#','#password#'.
For example, suppose the url is something like www.mysite.com/Action=Login?User=aj&Password=aj.
User Name (field)=User
Password (field)=Password
User Name (Value)=aj
Password (Value)=aj
Hidden variables(field)=Action=Login
Now, whenever any user logs into the liferay applicaiton, if his/her account exists in the site specified(in the url), it will log into that site automatically(acts like a single sign on).
This is working !!!
-Aj