Java Design patterns
This commit is contained in:
@@ -1,8 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public abstract class AbstractFactory {
|
|
||||||
abstract Shape getShape(String shapeType) ;
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class AbstractFactoryDemo {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
/* get shape factory */
|
|
||||||
AbstractFactory shapeFactory = FactoryOfFactory.getFactory(false);
|
|
||||||
/* get an object of Shape Rectangle */
|
|
||||||
Shape shape1 = shapeFactory.getShape("RECTANGLE");
|
|
||||||
/* call draw method of Shape Rectangle */
|
|
||||||
shape1.drawShape();
|
|
||||||
/* get an object of Shape Square */
|
|
||||||
Shape shape2 = shapeFactory.getShape("SQUARE");
|
|
||||||
/* call draw method of Shape Square */
|
|
||||||
shape2.drawShape();
|
|
||||||
/* get rounded shape factory */
|
|
||||||
AbstractFactory roundShapeFactory = FactoryOfFactory.getFactory(true);
|
|
||||||
/* get an object of Shape Rectangle */
|
|
||||||
Shape shape3 = roundShapeFactory.getShape("RECTANGLE");
|
|
||||||
/* call draw method of Shape Rectangle */
|
|
||||||
shape3.drawShape();
|
|
||||||
/* get an object of Shape Square */
|
|
||||||
Shape shape4 = roundShapeFactory.getShape("SQUARE");
|
|
||||||
/* call draw method of Shape Square */
|
|
||||||
shape4.drawShape();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class FactoryOfFactory {
|
|
||||||
public static AbstractFactory getFactory(boolean rounded){
|
|
||||||
if(rounded){
|
|
||||||
return new RoundedShapeFactory();
|
|
||||||
}else{
|
|
||||||
return new ShapeFactory();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class Rectangle implements Shape {
|
|
||||||
@Override
|
|
||||||
public void drawShape() {
|
|
||||||
System.out.println("Inside Rectangle::draw() method.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class RoundedRectangle implements Shape {
|
|
||||||
@Override
|
|
||||||
public void drawShape() {
|
|
||||||
System.out.println("Inside RoundedRectangle::draw() method.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class RoundedShapeFactory extends AbstractFactory {
|
|
||||||
@Override
|
|
||||||
public Shape getShape(String shapeType){
|
|
||||||
if(shapeType.equalsIgnoreCase("RECTANGLE")){
|
|
||||||
return new RoundedRectangle();
|
|
||||||
}else if(shapeType.equalsIgnoreCase("SQUARE")){
|
|
||||||
return new RoundedSquare();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class RoundedSquare implements Shape {
|
|
||||||
@Override
|
|
||||||
public void drawShape() {
|
|
||||||
System.out.println("Inside RoundedSquare::draw() method.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public interface Shape {
|
|
||||||
void drawShape();
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class ShapeFactory extends AbstractFactory {
|
|
||||||
@Override
|
|
||||||
public Shape getShape(String shapeType){
|
|
||||||
if(shapeType.equalsIgnoreCase("RECTANGLE")){
|
|
||||||
return new Rectangle();
|
|
||||||
}else if(shapeType.equalsIgnoreCase("SQUARE")){
|
|
||||||
return new Square();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class Square implements Shape {
|
|
||||||
@Override
|
|
||||||
public void drawShape() {
|
|
||||||
System.out.println("Inside Square::draw() method.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory.example2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract Factory - Factory of Factories
|
|
||||||
*/
|
|
||||||
public abstract class AbstractFactory{
|
|
||||||
abstract IMobile getMobile(String mobileModel) ;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory.example2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Client Class
|
|
||||||
*/
|
|
||||||
public class AbstractFactoryPatternDemo{
|
|
||||||
public static void main(String[] args){
|
|
||||||
AbstractFactory abstractFactory1 = MpbileFactoryProducer.getFactory(false);
|
|
||||||
IMobile onePlus = abstractFactory1.getMobile("Oneplus");
|
|
||||||
onePlus.brandName();
|
|
||||||
IMobile sony = abstractFactory1.getMobile("Sony");
|
|
||||||
sony.brandName();
|
|
||||||
IMobile lava = abstractFactory1.getMobile("Lava");
|
|
||||||
lava.brandName();
|
|
||||||
AbstractFactory abstractFactory2 = MpbileFactoryProducer.getFactory(true);
|
|
||||||
IMobile iphone = abstractFactory2.getMobile("iphone");
|
|
||||||
iphone.brandName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory.example2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Android Mobile Factory
|
|
||||||
*/
|
|
||||||
public class AndroidMobileFactory extends AbstractFactory {
|
|
||||||
@Override
|
|
||||||
public IMobile getMobile(String mobileModel){
|
|
||||||
if(mobileModel.equalsIgnoreCase("Oneplus")){
|
|
||||||
return new OnePlus();
|
|
||||||
}else if(mobileModel.equalsIgnoreCase("Sony")){
|
|
||||||
return new Sony();
|
|
||||||
}else if(mobileModel.equalsIgnoreCase("Lava")){
|
|
||||||
return new Lava();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory.example2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apple Mobile Factory
|
|
||||||
*/
|
|
||||||
public class AppleMobileFactory extends AbstractFactory{
|
|
||||||
@Override
|
|
||||||
public IMobile getMobile(String mobileModel){
|
|
||||||
if(mobileModel.equalsIgnoreCase("iphone")){
|
|
||||||
return new Iphone();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory.example2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mobile
|
|
||||||
*/
|
|
||||||
public interface IMobile {
|
|
||||||
void brandName();
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory.example2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Iphone Mobile
|
|
||||||
*/
|
|
||||||
public class Iphone implements IMobile {
|
|
||||||
@Override
|
|
||||||
public void brandName() {
|
|
||||||
System.out.println("The brand name is Iphone");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory.example2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Nokia Mobile Concrete Class
|
|
||||||
*/
|
|
||||||
public class Lava implements IMobile {
|
|
||||||
@Override
|
|
||||||
public void brandName() {
|
|
||||||
System.out.println("The brand name is Lava");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory.example2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory Producer
|
|
||||||
*/
|
|
||||||
public class MpbileFactoryProducer {
|
|
||||||
public static AbstractFactory getFactory(boolean isApple){
|
|
||||||
if(isApple){
|
|
||||||
return new AppleMobileFactory();
|
|
||||||
}else{
|
|
||||||
return new AndroidMobileFactory();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory.example2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OnePlus Mobile
|
|
||||||
*/
|
|
||||||
public class OnePlus implements IMobile {
|
|
||||||
@Override
|
|
||||||
public void brandName() {
|
|
||||||
System.out.println("The brand name is OnePlus");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package javadevjournal.design.creational.abstractfactory.example2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sony Mobile
|
|
||||||
*/
|
|
||||||
public class Sony implements IMobile {
|
|
||||||
@Override
|
|
||||||
public void brandName() {
|
|
||||||
System.out.println("The brand name is Sony");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package javadevjournal.design.creational.builder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
* Builder Pattern Client Class
|
|
||||||
* Create Computer object with mandatory and optional properties
|
|
||||||
*/
|
|
||||||
public class BuilderPatternDemo {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
|
|
||||||
Computer model1 = new Computer.ComputerBuilder(
|
|
||||||
"1 TB", "16 GB","15.6").setBluetoothEnabled(true)
|
|
||||||
.setGraphicsCardEnabled(true).setTouchScreenEnabled(true).setWebCamEnabled(true).build();
|
|
||||||
System.out.println("model1: " + model1.toString());
|
|
||||||
|
|
||||||
Computer model2 = new Computer.ComputerBuilder(
|
|
||||||
"256 GB", "8 GB","14.6").setBluetoothEnabled(true)
|
|
||||||
.setGraphicsCardEnabled(true).build();
|
|
||||||
System.out.println("model2: "+model2.toString());
|
|
||||||
|
|
||||||
|
|
||||||
Computer model3 = new Computer.ComputerBuilder(
|
|
||||||
"128 GB", "4 GB","13.6").build();
|
|
||||||
System.out.println("model3: "+model3.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
package javadevjournal.design.creational.builder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
* Product Class
|
|
||||||
* Builder Pattern Class
|
|
||||||
*/
|
|
||||||
public class Computer {
|
|
||||||
//required parameters
|
|
||||||
private String HDD;
|
|
||||||
private String RAM;
|
|
||||||
private String screenSize;
|
|
||||||
|
|
||||||
//optional parameters
|
|
||||||
private boolean isGraphicsCardEnabled;
|
|
||||||
private boolean isBluetoothEnabled;
|
|
||||||
private boolean isWebCamEnabled;
|
|
||||||
private boolean isTouchScreenEnabled;
|
|
||||||
|
|
||||||
public String getHDD() {
|
|
||||||
return HDD;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRAM() {
|
|
||||||
return RAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getScreenSize() {
|
|
||||||
return screenSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isGraphicsCardEnabled() {
|
|
||||||
return isGraphicsCardEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBluetoothEnabled() {
|
|
||||||
return isBluetoothEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isWebCamEnabled() {
|
|
||||||
return isWebCamEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTouchScreenEnabled() {
|
|
||||||
return isTouchScreenEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Computer(ComputerBuilder builder) {
|
|
||||||
this.HDD=builder.HDD;
|
|
||||||
this.RAM=builder.RAM;
|
|
||||||
this.screenSize=builder.screenSize;
|
|
||||||
this.isGraphicsCardEnabled=builder.isGraphicsCardEnabled;
|
|
||||||
this.isBluetoothEnabled=builder.isBluetoothEnabled;
|
|
||||||
this.isTouchScreenEnabled=builder.isTouchScreenEnabled;
|
|
||||||
this.isWebCamEnabled=builder.isWebCamEnabled;
|
|
||||||
this.isWebCamEnabled=builder.isWebCamEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Builder Class
|
|
||||||
public static class ComputerBuilder{
|
|
||||||
|
|
||||||
// required parameters
|
|
||||||
private String HDD;
|
|
||||||
private String RAM;
|
|
||||||
private String screenSize;
|
|
||||||
|
|
||||||
// optional parameters
|
|
||||||
private boolean isGraphicsCardEnabled;
|
|
||||||
private boolean isBluetoothEnabled;
|
|
||||||
private boolean isWebCamEnabled;
|
|
||||||
private boolean isTouchScreenEnabled;
|
|
||||||
|
|
||||||
public ComputerBuilder(String hdd, String ram, String screenSize){
|
|
||||||
this.HDD=hdd;
|
|
||||||
this.RAM=ram;
|
|
||||||
this.screenSize=screenSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ComputerBuilder setGraphicsCardEnabled(boolean isGraphicsCardEnabled) {
|
|
||||||
this.isGraphicsCardEnabled = isGraphicsCardEnabled;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ComputerBuilder setBluetoothEnabled(boolean isBluetoothEnabled) {
|
|
||||||
this.isBluetoothEnabled = isBluetoothEnabled;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ComputerBuilder setWebCamEnabled(boolean webCamEnabled) {
|
|
||||||
isWebCamEnabled = webCamEnabled;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ComputerBuilder setTouchScreenEnabled(boolean touchScreenEnabled) {
|
|
||||||
isTouchScreenEnabled = touchScreenEnabled;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Computer build(){
|
|
||||||
return new Computer(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Computer{" +
|
|
||||||
"HDD='" + HDD + '\'' +
|
|
||||||
", RAM='" + RAM + '\'' +
|
|
||||||
", screenSize='" + screenSize + '\'' +
|
|
||||||
", isGraphicsCardEnabled=" + isGraphicsCardEnabled +
|
|
||||||
", isBluetoothEnabled=" + isBluetoothEnabled +
|
|
||||||
", isWebCamEnabled=" + isWebCamEnabled +
|
|
||||||
", isTouchScreenEnabled=" + isTouchScreenEnabled +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package javadevjournal.design.creational.factory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class Circle implements Shape {
|
|
||||||
@Override
|
|
||||||
public void drawShape() {
|
|
||||||
System.out.println("Inside Circle::drawShape() method.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package javadevjournal.design.creational.factory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
* Factory Pattern Demo
|
|
||||||
*/
|
|
||||||
public class FactoryPatternDemo {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
ShapeFactory shapeFactory = new ShapeFactory();
|
|
||||||
|
|
||||||
/* get an object of Circle Class and call its drawShape method. */
|
|
||||||
Shape shape1 = shapeFactory.getShape("CIRCLE");
|
|
||||||
shape1.drawShape();
|
|
||||||
|
|
||||||
/* get an object of Rectangle Class and call its drawShape method. */
|
|
||||||
Shape shape2 = shapeFactory.getShape("RECTANGLE");
|
|
||||||
shape2.drawShape();
|
|
||||||
|
|
||||||
/* get an object of Square Class and call its drawShape method. */
|
|
||||||
Shape shape3 = shapeFactory.getShape("SQUARE");
|
|
||||||
shape3.drawShape();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package javadevjournal.design.creational.factory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class Rectangle implements Shape {
|
|
||||||
@Override
|
|
||||||
public void drawShape() {
|
|
||||||
System.out.println("Inside Rectangle::drawShape() method.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package javadevjournal.design.creational.factory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public interface Shape {
|
|
||||||
void drawShape();
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package javadevjournal.design.creational.factory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
* Factory Pattern Implementation here
|
|
||||||
*/
|
|
||||||
public class ShapeFactory {
|
|
||||||
/**
|
|
||||||
* get the shapeType from caller and decide the correct implementation class
|
|
||||||
* @param shapeType
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Shape getShape(String shapeType){
|
|
||||||
if(shapeType == null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if(shapeType.equalsIgnoreCase("CIRCLE")){
|
|
||||||
return new Circle();
|
|
||||||
|
|
||||||
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
|
|
||||||
return new Rectangle();
|
|
||||||
|
|
||||||
} else if(shapeType.equalsIgnoreCase("SQUARE")){
|
|
||||||
return new Square();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package javadevjournal.design.creational.factory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class Square implements Shape {
|
|
||||||
@Override
|
|
||||||
public void drawShape() {
|
|
||||||
System.out.println("Inside Square::drawShape() method.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package javadevjournal.design.creational.factory.banking;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public interface BankAccount {
|
|
||||||
public void registerAccount();
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package javadevjournal.design.creational.factory.banking;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class BankAccountFactory {
|
|
||||||
public BankAccount createAccount(String type){
|
|
||||||
BankAccount bankAccount = null;
|
|
||||||
if (type.equals("P")){
|
|
||||||
bankAccount = new PersonalAccount();
|
|
||||||
} else if (type.equals("B")){
|
|
||||||
bankAccount = new BusinessAccount();
|
|
||||||
} else if (type.equals("C")){
|
|
||||||
bankAccount = new CheckingAccount();
|
|
||||||
} else {
|
|
||||||
System.out.println("Invalid type");
|
|
||||||
}
|
|
||||||
return bankAccount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package javadevjournal.design.creational.factory.banking;
|
|
||||||
|
|
||||||
import java.util.Scanner;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class Branch {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
BankAccount bankAccount = null;
|
|
||||||
BankAccountFactory bankAccountFactory = new BankAccountFactory();
|
|
||||||
Scanner in = new Scanner(System.in);
|
|
||||||
System.out.println("Please enter\n" +
|
|
||||||
" P for Personal account\n" +
|
|
||||||
" B for Business account\n" +
|
|
||||||
" C for Checking account\n" +
|
|
||||||
"----------------------------");
|
|
||||||
String accountType = in.nextLine();
|
|
||||||
bankAccount = bankAccountFactory.createAccount(accountType);
|
|
||||||
bankAccount.registerAccount();;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package javadevjournal.design.creational.factory.banking;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class BusinessAccount implements BankAccount {
|
|
||||||
@Override
|
|
||||||
public void registerAccount() {
|
|
||||||
System.out.println("Creating a business account");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package javadevjournal.design.creational.factory.banking;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class CheckingAccount implements BankAccount{
|
|
||||||
@Override
|
|
||||||
public void registerAccount() {
|
|
||||||
System.out.println("Creating a checking account");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package javadevjournal.design.creational.factory.banking;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class PersonalAccount implements BankAccount{
|
|
||||||
@Override
|
|
||||||
public void registerAccount() {
|
|
||||||
System.out.println("Creating a personal account");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package javadevjournal.design.creational.singleton;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class Singleton {
|
|
||||||
|
|
||||||
/* private instance variable */
|
|
||||||
private static Singleton instance = new Singleton();
|
|
||||||
|
|
||||||
/* private constructor */
|
|
||||||
private Singleton(){}
|
|
||||||
|
|
||||||
/* returns the same object */
|
|
||||||
public static Singleton getInstance(){
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package javadevjournal.design.creational.singleton;
|
|
||||||
|
|
||||||
public class SingletonMultiThreaded {
|
|
||||||
|
|
||||||
/* private instance variable */
|
|
||||||
private static volatile SingletonMultiThreaded INSTANCE;
|
|
||||||
|
|
||||||
/* private constructor */
|
|
||||||
private SingletonMultiThreaded() { }
|
|
||||||
|
|
||||||
public static SingletonMultiThreaded getInstance() {
|
|
||||||
/* double-checking lock */
|
|
||||||
if(null == INSTANCE){
|
|
||||||
/* synchronized block */
|
|
||||||
synchronized (SingletonMultiThreaded.class) {
|
|
||||||
if(null == INSTANCE){
|
|
||||||
INSTANCE = new SingletonMultiThreaded();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package javadevjournal.design.creational.singleton;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class SingletonPatternDemo {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
/* Let's create 3 objects and see their hashcode and they will be same. */
|
|
||||||
System.out.println("in single threaded environment");
|
|
||||||
Singleton singleton1 = Singleton.getInstance();
|
|
||||||
Singleton singleton2 = Singleton.getInstance();
|
|
||||||
Singleton singleton3 = Singleton.getInstance();
|
|
||||||
System.out.println(singleton1.hashCode() +" "+ singleton2.hashCode() +" "+ singleton3.hashCode());
|
|
||||||
|
|
||||||
System.out.println("in multi threaded environment");
|
|
||||||
Thread1 t1 = new Thread1();
|
|
||||||
t1.run();
|
|
||||||
Thread2 t2 = new Thread2();
|
|
||||||
t2.run();
|
|
||||||
Thread3 t3 = new Thread3();
|
|
||||||
t3.run();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package javadevjournal.design.creational.singleton;
|
|
||||||
|
|
||||||
public class Thread1 implements Runnable{
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
SingletonMultiThreaded singletonMultiThreaded = SingletonMultiThreaded.getInstance();
|
|
||||||
System.out.print(singletonMultiThreaded.hashCode() + " ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package javadevjournal.design.creational.singleton;
|
|
||||||
|
|
||||||
public class Thread2 implements Runnable{
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
SingletonMultiThreaded singletonMultiThreaded = SingletonMultiThreaded.getInstance();
|
|
||||||
System.out.print(singletonMultiThreaded.hashCode() + " ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package javadevjournal.design.creational.singleton;
|
|
||||||
|
|
||||||
public class Thread3 implements Runnable{
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
SingletonMultiThreaded singletonMultiThreaded = SingletonMultiThreaded.getInstance();
|
|
||||||
System.out.println(singletonMultiThreaded.hashCode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package javadevjournal.design.creational.singleton.breakit;
|
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class BreakSingletonUsingReflection {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
Singleton singleton1 = Singleton.instance;
|
|
||||||
Singleton singleton2 = null;
|
|
||||||
try {
|
|
||||||
Constructor[] constructors =
|
|
||||||
Singleton.class.getDeclaredConstructors();
|
|
||||||
for (Constructor constructor : constructors) {
|
|
||||||
// Below code will destroy the singleton pattern
|
|
||||||
constructor.setAccessible(true);
|
|
||||||
singleton2 = (Singleton) constructor.newInstance();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
System.out.println("instance1.hashCode(): " + singleton1.hashCode());
|
|
||||||
System.out.println("instance2.hashCode(): " + singleton2.hashCode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package javadevjournal.design.creational.singleton.breakit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
class Singleton{
|
|
||||||
public static Singleton instance = new Singleton();
|
|
||||||
private Singleton() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package javadevjournal.design.structural.adapter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class AdapterPatternDemo {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
AudioPlayer audioPlayer = new AudioPlayer();
|
|
||||||
audioPlayer.playMusic("mp3", "song1.mp3");
|
|
||||||
audioPlayer.playMusic("mp4", "song2.mp4");
|
|
||||||
audioPlayer.playMusic("vlc", "song3.vlc");
|
|
||||||
audioPlayer.playMusic("xyz", "song4.avi");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package javadevjournal.design.structural.adapter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public interface AdvancedMediaPlayer {
|
|
||||||
void playVlcPlayer(String fileName);
|
|
||||||
void playMp4Player(String fileName);
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package javadevjournal.design.structural.adapter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class AudioPlayer implements MediaPlayer {
|
|
||||||
private MediaAdapter mediaAdapter;
|
|
||||||
@Override
|
|
||||||
public void playMusic(String audioType, String fileName) {
|
|
||||||
//the mp3 format is supported by AudioPlayer itself and it doesn't need adapter here.
|
|
||||||
if(audioType.equalsIgnoreCase("mp3")){
|
|
||||||
System.out.println("Playing mp3 file: " + fileName);
|
|
||||||
}
|
|
||||||
//to support other formats, we will need the MediaAdapter
|
|
||||||
else if(audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")){
|
|
||||||
mediaAdapter = new MediaAdapter(audioType);
|
|
||||||
mediaAdapter.playMusic(audioType, fileName);
|
|
||||||
}else{
|
|
||||||
System.out.println("The given format: " + audioType + " is not supported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package javadevjournal.design.structural.adapter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class MediaAdapter implements MediaPlayer {
|
|
||||||
|
|
||||||
public static final String VLC = "vlc";
|
|
||||||
public static final String MP_4 = "mp4";
|
|
||||||
|
|
||||||
private AdvancedMediaPlayer advancedMusicPlayer;
|
|
||||||
public MediaAdapter(String audioType){
|
|
||||||
if(audioType.equalsIgnoreCase(VLC) ){
|
|
||||||
advancedMusicPlayer = new VlcMusicPlayer();
|
|
||||||
}else if (audioType.equalsIgnoreCase(MP_4)){
|
|
||||||
advancedMusicPlayer = new Mp4MusicPlayer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playMusic(String audioType, String fileName) {
|
|
||||||
if(audioType.equalsIgnoreCase(VLC)){
|
|
||||||
advancedMusicPlayer.playVlcPlayer(fileName);
|
|
||||||
}else if(audioType.equalsIgnoreCase(MP_4)){
|
|
||||||
advancedMusicPlayer.playMp4Player(fileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package javadevjournal.design.structural.adapter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public interface MediaPlayer{
|
|
||||||
void playMusic(String audioType, String fileName);
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package javadevjournal.design.structural.adapter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class Mp4MusicPlayer implements AdvancedMediaPlayer{
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playVlcPlayer(String fileName) {
|
|
||||||
//do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playMp4Player(String fileName) {
|
|
||||||
System.out.println("Playing mp4 file: "+ fileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package javadevjournal.design.structural.adapter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Kunwar
|
|
||||||
*/
|
|
||||||
public class VlcMusicPlayer implements AdvancedMediaPlayer{
|
|
||||||
@Override
|
|
||||||
public void playVlcPlayer(String fileName){
|
|
||||||
System.out.println("Playing vlc file: "+ fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void playMp4Player(String fileName) {
|
|
||||||
//do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package javadevjournal.ds.avl;
|
|
||||||
|
|
||||||
class AVLNode{
|
|
||||||
|
|
||||||
AVLNode left, right;
|
|
||||||
int data;
|
|
||||||
int height;
|
|
||||||
|
|
||||||
public AVLNode(){
|
|
||||||
left = null;
|
|
||||||
right = null;
|
|
||||||
data = 0;
|
|
||||||
height = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AVLNode(int n){
|
|
||||||
left = null;
|
|
||||||
right = null;
|
|
||||||
data = n;
|
|
||||||
height = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,195 +0,0 @@
|
|||||||
package javadevjournal.ds.avl;
|
|
||||||
|
|
||||||
class AVLTree{
|
|
||||||
private AVLNode root;
|
|
||||||
public AVLTree(){
|
|
||||||
root = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param avlNode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private int height(AVLNode avlNode ){
|
|
||||||
return avlNode == null ? -1 : avlNode.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param lHeight
|
|
||||||
* @param rHeight
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private int max(int lHeight, int rHeight){
|
|
||||||
return lHeight > rHeight ? lHeight : rHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
*/
|
|
||||||
public void insert(int data){
|
|
||||||
root = insert(data, root);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
* @param avlNode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private AVLNode insert(int data, AVLNode avlNode)
|
|
||||||
{
|
|
||||||
if (avlNode == null)
|
|
||||||
avlNode = new AVLNode(data);
|
|
||||||
else if (data < avlNode.data){
|
|
||||||
avlNode.left = insert( data, avlNode.left );
|
|
||||||
if( height( avlNode.left ) - height( avlNode.right ) == 2 )
|
|
||||||
if( data < avlNode.left.data )
|
|
||||||
avlNode = leftRotation( avlNode );
|
|
||||||
else
|
|
||||||
avlNode = leftRightRotation( avlNode );
|
|
||||||
}
|
|
||||||
else if( data > avlNode.data ){
|
|
||||||
avlNode.right = insert( data, avlNode.right );
|
|
||||||
if( height( avlNode.right ) - height( avlNode.left ) == 2 )
|
|
||||||
if( data > avlNode.right.data)
|
|
||||||
avlNode = rightRotation( avlNode );
|
|
||||||
else
|
|
||||||
avlNode = rightLeftRotation( avlNode );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
; // Duplicate; do nothing
|
|
||||||
avlNode.height = max( height( avlNode.left ), height( avlNode.right ) ) + 1;
|
|
||||||
return avlNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param avlNode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private AVLNode leftRotation(AVLNode avlNode){
|
|
||||||
AVLNode k1 = avlNode.left;
|
|
||||||
avlNode.left = k1.right;
|
|
||||||
k1.right = avlNode;
|
|
||||||
avlNode.height = max( height( avlNode.left ), height( avlNode.right ) ) + 1;
|
|
||||||
k1.height = max( height( k1.left ), avlNode.height ) + 1;
|
|
||||||
return k1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param avlNode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private AVLNode rightRotation(AVLNode avlNode){
|
|
||||||
AVLNode node = avlNode.right;
|
|
||||||
avlNode.right = node.left;
|
|
||||||
node.left = avlNode;
|
|
||||||
avlNode.height = max( height( avlNode.left ), height( avlNode.right ) ) + 1;
|
|
||||||
node.height = max( height( node.right ), avlNode.height ) + 1;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* left-right rotation
|
|
||||||
* @param avlNode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private AVLNode leftRightRotation(AVLNode avlNode){
|
|
||||||
avlNode.left = rightRotation( avlNode.left );
|
|
||||||
return leftRotation( avlNode );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* right-left rotation
|
|
||||||
* @param avlNode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private AVLNode rightLeftRotation(AVLNode avlNode)
|
|
||||||
{
|
|
||||||
avlNode.right = leftRotation( avlNode.right );
|
|
||||||
return rightRotation( avlNode );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public int countNodes(){
|
|
||||||
return countNodes(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param avlNode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private int countNodes(AVLNode avlNode){
|
|
||||||
if (avlNode == null)
|
|
||||||
return 0;
|
|
||||||
else{
|
|
||||||
int l = 1;
|
|
||||||
l += countNodes(avlNode.left);
|
|
||||||
l += countNodes(avlNode.right);
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean search(int data){
|
|
||||||
return search(root, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param avlNode
|
|
||||||
* @param data
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private boolean search(AVLNode avlNode, int data){
|
|
||||||
boolean found = false;
|
|
||||||
while ((avlNode != null) && !found)
|
|
||||||
{
|
|
||||||
int rval = avlNode.data;
|
|
||||||
if (data < rval)
|
|
||||||
avlNode = avlNode.left;
|
|
||||||
else if (data > rval)
|
|
||||||
avlNode = avlNode.right;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
found = search(avlNode, data);
|
|
||||||
}
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void inorder(){
|
|
||||||
inorder(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param avlNode
|
|
||||||
*/
|
|
||||||
private void inorder(AVLNode avlNode){
|
|
||||||
if (avlNode != null){
|
|
||||||
inorder(avlNode.left);
|
|
||||||
System.out.print(avlNode.data +" ");
|
|
||||||
inorder(avlNode.right);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
package javadevjournal.ds.avl;
|
|
||||||
|
|
||||||
import java.util.Scanner;
|
|
||||||
|
|
||||||
public class AVLTreeHelper{
|
|
||||||
public static void main(String[] args){
|
|
||||||
Scanner scanner = new Scanner(System.in);
|
|
||||||
AVLTree avlTree = new AVLTree();
|
|
||||||
|
|
||||||
char ch;
|
|
||||||
do{
|
|
||||||
System.out.println("\nAVLTree Operations\n");
|
|
||||||
System.out.println("1. insert ");
|
|
||||||
System.out.println("2. search");
|
|
||||||
System.out.println("3. count nodes");
|
|
||||||
int choice = scanner.nextInt();
|
|
||||||
switch (choice)
|
|
||||||
{
|
|
||||||
case 1 :
|
|
||||||
System.out.println("Enter integer element to insert");
|
|
||||||
avlTree.insert( scanner.nextInt() );
|
|
||||||
break;
|
|
||||||
case 2 :
|
|
||||||
System.out.println("Enter integer element to search");
|
|
||||||
System.out.println("Search result : "+ avlTree.search( scanner.nextInt()));
|
|
||||||
break;
|
|
||||||
case 3 :
|
|
||||||
System.out.println("Nodes = "+ avlTree.countNodes());
|
|
||||||
break;
|
|
||||||
default :
|
|
||||||
System.out.println("Wrong Entry \n ");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.print("\nIn order : ");
|
|
||||||
avlTree.inorder();
|
|
||||||
|
|
||||||
System.out.println("\nDo you want to continue (Type y or n) \n");
|
|
||||||
ch = scanner.next().charAt(0);
|
|
||||||
} while (ch == 'Y'|| ch == 'y');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
8
java-tutorials/.idea/.gitignore
generated
vendored
Normal file
8
java-tutorials/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
5
java-tutorials/.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
java-tutorials/.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
@@ -122,19 +122,31 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>org.apache.directory.server</groupId>-->
|
||||||
|
<!-- <artifactId>apacheds-core</artifactId>-->
|
||||||
|
<!-- <version>1.5.7</version>-->
|
||||||
|
<!-- <scope>runtime</scope>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>org.apache.directory.server</groupId>-->
|
||||||
|
<!-- <artifactId>apacheds-server-jndi</artifactId>-->
|
||||||
|
<!-- <version>1.5.7</version>-->
|
||||||
|
<!-- <scope>runtime</scope>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.directory.server</groupId>
|
<groupId>com.unboundid</groupId>
|
||||||
<artifactId>apacheds-core</artifactId>
|
<artifactId>unboundid-ldapsdk</artifactId>
|
||||||
<version>1.5.7</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.directory.server</groupId>
|
|
||||||
<artifactId>apacheds-server-jndi</artifactId>
|
|
||||||
<version>1.5.7</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- dependency for the MFA -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>dev.samstevens.totp</groupId>
|
||||||
|
<artifactId>totp</artifactId>
|
||||||
|
<version>1.7.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -1,142 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
|
||||||
<output url="file://$MODULE_DIR$/target/classes" />
|
|
||||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-devtools:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.2.7.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.13.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.13.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.30" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: jakarta.annotation:jakarta.annotation-api:1.3.5" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.2.7.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.2.7.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.26" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-security:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.2.7.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.2.7.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-config:5.3.3.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:5.3.3.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-web:5.3.3.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.2.7.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.11.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.11.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.11.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.11.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.11.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.11.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.36" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.36" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework:spring-web:5.2.7.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.2.7.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-validation:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.glassfish:jakarta.el:3.0.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.hibernate.validator:hibernate-validator:6.1.5.Final" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: jakarta.validation:jakarta.validation-api:2.0.2" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.4.1.Final" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.fasterxml:classmate:1.5.1" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-thymeleaf:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.thymeleaf:thymeleaf-spring5:3.0.11.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.thymeleaf:thymeleaf:3.0.11.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.attoparser:attoparser:2.0.5.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.unbescape:unbescape:1.1.6.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.thymeleaf.extras:thymeleaf-extras-java8time:3.0.4.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-data-jpa:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-aop:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.aspectj:aspectjweaver:1.9.5" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.zaxxer:HikariCP:3.4.5" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.2.7.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: jakarta.transaction:jakarta.transaction-api:1.3.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: jakarta.persistence:jakarta.persistence-api:2.2.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.hibernate:hibernate-core:5.4.17.Final" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.javassist:javassist:3.24.0-GA" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: net.bytebuddy:byte-buddy:1.10.11" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: antlr:antlr:2.7.7" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.jboss:jandex:2.1.3.Final" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.dom4j:dom4j:2.1.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.hibernate.common:hibernate-commons-annotations:5.1.0.Final" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.glassfish.jaxb:jaxb-runtime:2.3.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.glassfish.jaxb:txw2:2.3.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.sun.istack:istack-commons-runtime:3.0.11" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-jpa:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-commons:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework:spring-orm:5.2.7.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework:spring-tx:5.2.7.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework:spring-aspects:5.2.7.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-actuator:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-actuator-autoconfigure:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-actuator:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: io.micrometer:micrometer-core:1.5.1" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.hdrhistogram:HdrHistogram:2.1.12" level="project" />
|
|
||||||
<orderEntry type="library" scope="RUNTIME" name="Maven: org.latencyutils:LatencyUtils:2.0.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:8.0.18" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-mail:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework:spring-context-support:5.2.7.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.sun.mail:jakarta.mail:1.6.5" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.sun.activation:jakarta.activation:1.2.2" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.11" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.0.4.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.30" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.session:spring-session-data-redis:2.3.0.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-redis:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-keyvalue:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework:spring-oxm:5.2.7.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.session:spring-session-core:2.3.0.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-data-redis:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: io.lettuce:lettuce-core:5.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: io.netty:netty-common:4.1.50.Final" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: io.netty:netty-handler:4.1.50.Final" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: io.netty:netty-resolver:4.1.50.Final" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: io.netty:netty-buffer:4.1.50.Final" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: io.netty:netty-codec:4.1.50.Final" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: io.netty:netty-transport:4.1.50.Final" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: io.projectreactor:reactor-core:3.3.6.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.reactivestreams:reactive-streams:1.0.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-collections4:4.4" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:2.3.1.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.4.0" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.3" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.2" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:5.0.4" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: jakarta.xml.bind:jakarta.xml.bind-api:2.3.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: jakarta.activation:jakarta.activation-api:1.2.2" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:3.16.1" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest:2.2" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter:5.6.2" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-api:5.6.2" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.0" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.opentest4j:opentest4j:1.2.0" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-commons:1.6.2" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-params:5.6.2" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-engine:5.6.2" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-engine:1.6.2" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:3.3.3" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy-agent:1.10.11" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.6" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-junit-jupiter:3.3.3" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.5.0" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:5.2.7.RELEASE" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: org.xmlunit:xmlunit-core:2.7.0" level="project" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
||||||
@@ -1,5 +1,14 @@
|
|||||||
package com.javadevjournal.config;
|
package com.javadevjournal.config;
|
||||||
|
|
||||||
|
import dev.samstevens.totp.code.CodeVerifier;
|
||||||
|
import dev.samstevens.totp.code.DefaultCodeGenerator;
|
||||||
|
import dev.samstevens.totp.code.DefaultCodeVerifier;
|
||||||
|
import dev.samstevens.totp.qr.QrGenerator;
|
||||||
|
import dev.samstevens.totp.qr.ZxingPngQrGenerator;
|
||||||
|
import dev.samstevens.totp.secret.DefaultSecretGenerator;
|
||||||
|
import dev.samstevens.totp.secret.SecretGenerator;
|
||||||
|
import dev.samstevens.totp.time.SystemTimeProvider;
|
||||||
|
import dev.samstevens.totp.time.TimeProvider;
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.MessageSource;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@@ -68,4 +77,20 @@ public class AppConfig implements WebMvcConfigurer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setting up thymeleaf for Spring Email TemplateEngine
|
// setting up thymeleaf for Spring Email TemplateEngine
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SecretGenerator secretGenerator(){
|
||||||
|
return new DefaultSecretGenerator(64);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public QrGenerator qrGenerator(){
|
||||||
|
return new ZxingPngQrGenerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public CodeVerifier codeVerifier(){
|
||||||
|
return new DefaultCodeVerifier(new DefaultCodeGenerator(), new SystemTimeProvider());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,36 +2,28 @@ package com.javadevjournal.core.security;
|
|||||||
|
|
||||||
import com.javadevjournal.core.security.authentication.CustomAuthenticationProvider;
|
import com.javadevjournal.core.security.authentication.CustomAuthenticationProvider;
|
||||||
import com.javadevjournal.core.security.filter.CustomAuthenticationFilter;
|
import com.javadevjournal.core.security.filter.CustomAuthenticationFilter;
|
||||||
import com.javadevjournal.core.security.filter.CustomHeaderAuthFilter;
|
|
||||||
import com.javadevjournal.core.security.handlers.CustomAccessDeniedHandler;
|
import com.javadevjournal.core.security.handlers.CustomAccessDeniedHandler;
|
||||||
import com.javadevjournal.core.security.handlers.CustomSuccessHandler;
|
import com.javadevjournal.core.security.handlers.CustomSuccessHandler;
|
||||||
import com.javadevjournal.core.security.handlers.LoginAuthenticationFailureHandler;
|
import com.javadevjournal.core.security.handlers.LoginAuthenticationFailureHandler;
|
||||||
import com.javadevjournal.core.security.web.authentication.CustomWebAuthenticationDetails;
|
import com.javadevjournal.core.security.web.authentication.CustomWebAuthenticationDetails;
|
||||||
|
import com.javadevjournal.core.security.web.authentication.CustomWebAuthenticationDetailsSource;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
|
|
||||||
import org.springframework.context.ApplicationEventPublisher;
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
|
|
||||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||||
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
import org.springframework.security.authentication.AuthenticationEventPublisher;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
|
||||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
import org.springframework.security.config.annotation.authentication.configurers.ldap.LdapAuthenticationProviderConfigurer;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
|
||||||
import org.springframework.security.core.session.SessionRegistry;
|
import org.springframework.security.core.session.SessionRegistry;
|
||||||
import org.springframework.security.core.session.SessionRegistryImpl;
|
import org.springframework.security.core.session.SessionRegistryImpl;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.security.ldap.authentication.BindAuthenticator;
|
|
||||||
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
|
|
||||||
import org.springframework.security.ldap.authentication.LdapAuthenticator;
|
|
||||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
|
||||||
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||||
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
|
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
|
||||||
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
|
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
|
||||||
@@ -47,14 +39,17 @@ public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
@Resource
|
@Resource
|
||||||
UserDetailsService userDetailsService;
|
UserDetailsService userDetailsService;
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
PasswordEncoder passwordEncoder;
|
PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
CustomAuthenticationProvider customAuthenticationProvider;
|
private CustomAuthenticationProvider customAuthenticationProvider;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CustomWebAuthenticationDetailsSource authenticationDetailsSource;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
@@ -68,7 +63,6 @@ public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
//Setting HTTPS for my account
|
//Setting HTTPS for my account
|
||||||
.requiresChannel().anyRequest().requiresSecure()
|
.requiresChannel().anyRequest().requiresSecure()
|
||||||
.and()
|
.and()
|
||||||
|
|
||||||
// Remember me configurations
|
// Remember me configurations
|
||||||
.rememberMe().tokenRepository(persistentTokenRepository())
|
.rememberMe().tokenRepository(persistentTokenRepository())
|
||||||
.rememberMeCookieDomain("domain")
|
.rememberMeCookieDomain("domain")
|
||||||
@@ -85,6 +79,7 @@ public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
.failureUrl("/login?error=true")
|
.failureUrl("/login?error=true")
|
||||||
.successHandler(successHandler())
|
.successHandler(successHandler())
|
||||||
.failureHandler(failureHandler())
|
.failureHandler(failureHandler())
|
||||||
|
.authenticationDetailsSource(authenticationDetailsSource) //injecting custom authenitcation source
|
||||||
//logout configurations
|
//logout configurations
|
||||||
.and()
|
.and()
|
||||||
.logout().deleteCookies("dummyCookie")
|
.logout().deleteCookies("dummyCookie")
|
||||||
@@ -97,15 +92,16 @@ public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
|
|
||||||
|
|
||||||
http.authorizeRequests().antMatchers("/admim/**").hasAuthority("ADMIN");
|
http.authorizeRequests().antMatchers("/admim/**").hasAuthority("ADMIN");
|
||||||
http.addFilterAfter(customHeaderAuthFilter(), UsernamePasswordAuthenticationFilter.class);
|
//http.addFilterAfter(customHeaderAuthFilter(), UsernamePasswordAuthenticationFilter.class);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
|
/* @Bean
|
||||||
public CustomHeaderAuthFilter customHeaderAuthFilter(){
|
public CustomHeaderAuthFilter customHeaderAuthFilter(){
|
||||||
return new CustomHeaderAuthFilter();
|
return new CustomHeaderAuthFilter();
|
||||||
}
|
} */
|
||||||
|
|
||||||
|
|
||||||
private AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> authenticationDetailsSource() {
|
private AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> authenticationDetailsSource() {
|
||||||
@@ -138,14 +134,14 @@ public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
return new CustomAccessDeniedHandler();
|
return new CustomAccessDeniedHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
/* @Bean
|
||||||
public CustomAuthenticationFilter authFilter() throws Exception {
|
public CustomAuthenticationFilter authFilter() throws Exception {
|
||||||
CustomAuthenticationFilter filter = new CustomAuthenticationFilter();
|
CustomAuthenticationFilter filter = new CustomAuthenticationFilter();
|
||||||
filter.setAuthenticationManager(authenticationManagerBean());
|
filter.setAuthenticationManager(authenticationManagerBean());
|
||||||
filter.setAuthenticationFailureHandler(failureHandler());
|
filter.setAuthenticationFailureHandler(failureHandler());
|
||||||
filter.setAuthenticationSuccessHandler(successHandler());
|
filter.setAuthenticationSuccessHandler(successHandler());
|
||||||
return filter;
|
return filter;
|
||||||
}
|
} */
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public LoginAuthenticationFailureHandler failureHandler(){
|
public LoginAuthenticationFailureHandler failureHandler(){
|
||||||
@@ -188,14 +184,13 @@ public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
* DAO authentication provider. This authentication provider will authenticate the user with the help of
|
* DAO authentication provider. This authentication provider will authenticate the user with the help of
|
||||||
* @UserdetailsService. This is based on the validating the user with the username and password.
|
* @UserdetailsService. This is based on the validating the user with the username and password.
|
||||||
* @return
|
* @return
|
||||||
*/
|
|
||||||
@Bean
|
@Bean
|
||||||
public DaoAuthenticationProvider authProvider() {
|
public CustomAuthenticationProvider authProvider() {
|
||||||
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
|
CustomAuthenticationProvider authenticationProvider = new CustomAuthenticationProvider();
|
||||||
authenticationProvider.setPasswordEncoder(passwordEncoder);
|
|
||||||
authenticationProvider.setUserDetailsService(userDetailsService);
|
authenticationProvider.setUserDetailsService(userDetailsService);
|
||||||
return authenticationProvider;
|
return authenticationProvider;
|
||||||
}
|
} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authentication manager which will be invoked by Spring security filter chain. This authentication
|
* Authentication manager which will be invoked by Spring security filter chain. This authentication
|
||||||
@@ -206,11 +201,11 @@ public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void configure(AuthenticationManagerBuilder auth){
|
protected void configure(AuthenticationManagerBuilder auth){
|
||||||
//auth.authenticationProvider(authProvider());
|
auth.authenticationProvider(customAuthenticationProvider);
|
||||||
auth.authenticationProvider(customAuthenticationProvider)
|
//auth.authenticationProvider(customAuthenticationProvider).authenticationProvider(authProvider());
|
||||||
.authenticationProvider(authProvider());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Using this to persist the remember-me token in the database for more secure approach.
|
* Using this to persist the remember-me token in the database for more secure approach.
|
||||||
* We are not usin gthe memory based remember-me cookie which is not very secure but saving the token in the
|
* We are not usin gthe memory based remember-me cookie which is not very secure but saving the token in the
|
||||||
@@ -226,6 +221,7 @@ public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
|
|
||||||
//Spring security LDAP configurations
|
//Spring security LDAP configurations
|
||||||
|
|
||||||
|
/*
|
||||||
@Bean
|
@Bean
|
||||||
BindAuthenticator authenticator(BaseLdapPathContextSource contextSource) {
|
BindAuthenticator authenticator(BaseLdapPathContextSource contextSource) {
|
||||||
BindAuthenticator authenticator = new BindAuthenticator(contextSource);
|
BindAuthenticator authenticator = new BindAuthenticator(contextSource);
|
||||||
@@ -237,5 +233,5 @@ public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
@Bean
|
@Bean
|
||||||
LdapAuthenticationProvider authenticationProvider(LdapAuthenticator authenticator) {
|
LdapAuthenticationProvider authenticationProvider(LdapAuthenticator authenticator) {
|
||||||
return new LdapAuthenticationProvider(authenticator);
|
return new LdapAuthenticationProvider(authenticator);
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +1,51 @@
|
|||||||
package com.javadevjournal.core.security.authentication;
|
package com.javadevjournal.core.security.authentication;
|
||||||
|
|
||||||
import org.springframework.security.authentication.AuthenticationProvider;
|
|
||||||
|
import com.javadevjournal.core.security.core.userdetail.CustomUser;
|
||||||
|
import com.javadevjournal.core.security.mfa.MFATokenManager;
|
||||||
|
import com.javadevjournal.core.security.web.authentication.CustomWebAuthenticationDetails;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class CustomAuthenticationProvider implements AuthenticationProvider {
|
public class CustomAuthenticationProvider extends DaoAuthenticationProvider {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
UserDetailsService userDetailsService;
|
private MFATokenManager mfaTokenManager;
|
||||||
|
|
||||||
@Override
|
@Resource
|
||||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
private PasswordEncoder passwordEncoder;
|
||||||
final String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName();
|
|
||||||
|
|
||||||
if (StringUtils.isEmpty(username)) {
|
@Autowired
|
||||||
throw new BadCredentialsException("invalid login details");
|
public CustomAuthenticationProvider(UserDetailsService userDetailsService) {
|
||||||
|
super.setUserDetailsService(userDetailsService);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void additionalAuthenticationChecks(UserDetails userDetails,
|
||||||
|
UsernamePasswordAuthenticationToken authentication)
|
||||||
|
throws AuthenticationException {
|
||||||
|
|
||||||
|
super.additionalAuthenticationChecks(userDetails, authentication);
|
||||||
|
|
||||||
|
//token check
|
||||||
|
CustomWebAuthenticationDetails authenticationDetails = (CustomWebAuthenticationDetails) authentication.getDetails();
|
||||||
|
CustomUser user = (CustomUser) userDetails;
|
||||||
|
String mfaToken = authenticationDetails.getToken();
|
||||||
|
if(!mfaTokenManager.verifyTotp(mfaToken,user.getSecret())){
|
||||||
|
throw new BadCredentialsException(messages.getMessage(
|
||||||
|
"AbstractUserDetailsAuthenticationProvider.badCredentials",
|
||||||
|
"Bad credentials"));
|
||||||
}
|
}
|
||||||
// get user details using Spring security user details service
|
|
||||||
UserDetails user = null;
|
|
||||||
try {
|
|
||||||
user = userDetailsService.loadUserByUsername(username);
|
|
||||||
|
|
||||||
} catch (UsernameNotFoundException exception) {
|
|
||||||
throw new BadCredentialsException("invalid login details");
|
|
||||||
}
|
|
||||||
return createSuccessfulAuthentication(authentication, user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Authentication createSuccessfulAuthentication(final Authentication authentication, final UserDetails user) {
|
|
||||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user.getUsername(), authentication.getCredentials(), user.getAuthorities());
|
|
||||||
token.setDetails(authentication.getDetails());
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supports(Class<?> authentication) {
|
|
||||||
return authentication.equals(UsernamePasswordAuthenticationToken.class);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,21 +13,22 @@ import java.util.function.Function;
|
|||||||
public class CustomUser implements UserDetails {
|
public class CustomUser implements UserDetails {
|
||||||
|
|
||||||
private String password;
|
private String password;
|
||||||
private final String username;
|
private String username;
|
||||||
private final Set<GrantedAuthority> authorities;
|
private Collection<GrantedAuthority> authorities;
|
||||||
private final boolean accountNonExpired;
|
private boolean accountNonExpired;
|
||||||
private final boolean accountNonLocked;
|
private boolean accountNonLocked;
|
||||||
private final boolean credentialsNonExpired;
|
private boolean credentialsNonExpired;
|
||||||
private final boolean enabled;
|
private boolean enabled;
|
||||||
|
private String secret;
|
||||||
|
|
||||||
public CustomUser(String username, String password,
|
public CustomUser(String username, String password,
|
||||||
Collection<? extends GrantedAuthority> authorities) {
|
Collection<? extends GrantedAuthority> authorities, String secret) {
|
||||||
this(username, password, true, true, true, true, authorities);
|
this(username, password, true, true, true, true, authorities, secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CustomUser(String username, String password, boolean enabled,
|
public CustomUser(String username, String password, boolean enabled,
|
||||||
boolean accountNonExpired, boolean credentialsNonExpired,
|
boolean accountNonExpired, boolean credentialsNonExpired,
|
||||||
boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
|
boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities, final String secret) {
|
||||||
|
|
||||||
if (((username == null) || "".equals(username)) || (password == null)) {
|
if (((username == null) || "".equals(username)) || (password == null)) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
@@ -41,6 +42,7 @@ public class CustomUser implements UserDetails {
|
|||||||
this.credentialsNonExpired = credentialsNonExpired;
|
this.credentialsNonExpired = credentialsNonExpired;
|
||||||
this.accountNonLocked = accountNonLocked;
|
this.accountNonLocked = accountNonLocked;
|
||||||
this.authorities = null;
|
this.authorities = null;
|
||||||
|
this.secret= secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -76,6 +78,10 @@ public class CustomUser implements UserDetails {
|
|||||||
password = null;
|
password = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSecret() {
|
||||||
|
return secret;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object rhs) {
|
public boolean equals(Object rhs) {
|
||||||
if (rhs instanceof CustomUser) {
|
if (rhs instanceof CustomUser) {
|
||||||
@@ -89,209 +95,68 @@ public class CustomUser implements UserDetails {
|
|||||||
return username.hashCode();
|
return username.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CustomUser.UserBuilder withUsername(String username) {
|
|
||||||
return builder().username(username);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CustomUser.UserBuilder builder() {
|
public static final class CustomUserBuilder {
|
||||||
return new CustomUser.UserBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CustomUser.UserBuilder withUserDetails(UserDetails userDetails) {
|
|
||||||
return withUsername(userDetails.getUsername())
|
|
||||||
.password(userDetails.getPassword())
|
|
||||||
.accountExpired(!userDetails.isAccountNonExpired())
|
|
||||||
.accountLocked(!userDetails.isAccountNonLocked())
|
|
||||||
.authorities(userDetails.getAuthorities())
|
|
||||||
.credentialsExpired(!userDetails.isCredentialsNonExpired())
|
|
||||||
.disabled(!userDetails.isEnabled());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class UserBuilder {
|
|
||||||
private String username;
|
|
||||||
private String password;
|
private String password;
|
||||||
private List<GrantedAuthority> authorities;
|
private String username;
|
||||||
private boolean accountExpired;
|
private Collection<GrantedAuthority> authorities;
|
||||||
private boolean accountLocked;
|
private boolean accountNonExpired;
|
||||||
private boolean credentialsExpired;
|
private boolean accountNonLocked;
|
||||||
private boolean disabled;
|
private boolean credentialsNonExpired;
|
||||||
private Function<String, String> passwordEncoder = password -> password;
|
private boolean enabled;
|
||||||
|
private String secret;
|
||||||
|
|
||||||
/**
|
private CustomUserBuilder() {
|
||||||
* Creates a new instance
|
|
||||||
*/
|
|
||||||
private UserBuilder() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static CustomUserBuilder aCustomUser() {
|
||||||
* Populates the username. This attribute is required.
|
return new CustomUserBuilder();
|
||||||
*
|
|
||||||
* @param username the username. Cannot be null.
|
|
||||||
* @return the {@link User.UserBuilder} for method chaining (i.e. to populate
|
|
||||||
* additional attributes for this user)
|
|
||||||
*/
|
|
||||||
public CustomUser.UserBuilder username(String username) {
|
|
||||||
Assert.notNull(username, "username cannot be null");
|
|
||||||
this.username = username;
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public CustomUserBuilder withPassword(String password) {
|
||||||
* Populates the password. This attribute is required.
|
|
||||||
*
|
|
||||||
* @param password the password. Cannot be null.
|
|
||||||
* @return the {@link User.UserBuilder} for method chaining (i.e. to populate
|
|
||||||
* additional attributes for this user)
|
|
||||||
*/
|
|
||||||
public CustomUser.UserBuilder password(String password) {
|
|
||||||
Assert.notNull(password, "password cannot be null");
|
|
||||||
this.password = password;
|
this.password = password;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public CustomUserBuilder withUsername(String username) {
|
||||||
* Encodes the current password (if non-null) and any future passwords supplied
|
this.username = username;
|
||||||
* to {@link #password(String)}.
|
|
||||||
*
|
|
||||||
* @param encoder the encoder to use
|
|
||||||
* @return the {@link User.UserBuilder} for method chaining (i.e. to populate
|
|
||||||
* additional attributes for this user)
|
|
||||||
*/
|
|
||||||
public CustomUser.UserBuilder passwordEncoder(Function<String, String> encoder) {
|
|
||||||
Assert.notNull(encoder, "encoder cannot be null");
|
|
||||||
this.passwordEncoder = encoder;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public CustomUserBuilder withAuthorities(Collection<GrantedAuthority> authorities) {
|
||||||
* Populates the roles. This method is a shortcut for calling
|
this.authorities = authorities;
|
||||||
* {@link #authorities(String...)}, but automatically prefixes each entry with
|
|
||||||
* "ROLE_". This means the following:
|
|
||||||
*
|
|
||||||
* <code>
|
|
||||||
* builder.roles("USER","ADMIN");
|
|
||||||
* </code>
|
|
||||||
*
|
|
||||||
* is equivalent to
|
|
||||||
*
|
|
||||||
* <code>
|
|
||||||
* builder.authorities("ROLE_USER","ROLE_ADMIN");
|
|
||||||
* </code>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This attribute is required, but can also be populated with
|
|
||||||
* {@link #authorities(String...)}.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param roles the roles for this user (i.e. USER, ADMIN, etc). Cannot be null,
|
|
||||||
* contain null values or start with "ROLE_"
|
|
||||||
* @return the {@link User.UserBuilder} for method chaining (i.e. to populate
|
|
||||||
* additional attributes for this user)
|
|
||||||
*/
|
|
||||||
public CustomUser.UserBuilder roles(String... roles) {
|
|
||||||
List<GrantedAuthority> authorities = new ArrayList<>(
|
|
||||||
roles.length);
|
|
||||||
for (String role : roles) {
|
|
||||||
Assert.isTrue(!role.startsWith("ROLE_"), () -> role
|
|
||||||
+ " cannot start with ROLE_ (it is automatically added)");
|
|
||||||
authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
|
|
||||||
}
|
|
||||||
return authorities(authorities);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates the authorities. This attribute is required.
|
|
||||||
*
|
|
||||||
* @param authorities the authorities for this user. Cannot be null, or contain
|
|
||||||
* null values
|
|
||||||
* @return the {@link User.UserBuilder} for method chaining (i.e. to populate
|
|
||||||
* additional attributes for this user)
|
|
||||||
* @see #roles(String...)
|
|
||||||
*/
|
|
||||||
public CustomUser.UserBuilder authorities(GrantedAuthority... authorities) {
|
|
||||||
return authorities(Arrays.asList(authorities));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates the authorities. This attribute is required.
|
|
||||||
*
|
|
||||||
* @param authorities the authorities for this user. Cannot be null, or contain
|
|
||||||
* null values
|
|
||||||
* @return the {@link User.UserBuilder} for method chaining (i.e. to populate
|
|
||||||
* additional attributes for this user)
|
|
||||||
* @see #roles(String...)
|
|
||||||
*/
|
|
||||||
public CustomUser.UserBuilder authorities(Collection<? extends GrantedAuthority> authorities) {
|
|
||||||
this.authorities = new ArrayList<>(authorities);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public CustomUserBuilder withAccountNonExpired(boolean accountNonExpired) {
|
||||||
* Populates the authorities. This attribute is required.
|
this.accountNonExpired = accountNonExpired;
|
||||||
*
|
|
||||||
* @param authorities the authorities for this user (i.e. ROLE_USER, ROLE_ADMIN,
|
|
||||||
* etc). Cannot be null, or contain null values
|
|
||||||
* @return the {@link User.UserBuilder} for method chaining (i.e. to populate
|
|
||||||
* additional attributes for this user)
|
|
||||||
* @see #roles(String...)
|
|
||||||
*/
|
|
||||||
public CustomUser.UserBuilder authorities(String... authorities) {
|
|
||||||
return authorities(AuthorityUtils.createAuthorityList(authorities));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines if the account is expired or not. Default is false.
|
|
||||||
*
|
|
||||||
* @param accountExpired true if the account is expired, false otherwise
|
|
||||||
* @return the {@link User.UserBuilder} for method chaining (i.e. to populate
|
|
||||||
* additional attributes for this user)
|
|
||||||
*/
|
|
||||||
public CustomUser.UserBuilder accountExpired(boolean accountExpired) {
|
|
||||||
this.accountExpired = accountExpired;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public CustomUserBuilder withAccountNonLocked(boolean accountNonLocked) {
|
||||||
* Defines if the account is locked or not. Default is false.
|
this.accountNonLocked = accountNonLocked;
|
||||||
*
|
|
||||||
* @param accountLocked true if the account is locked, false otherwise
|
|
||||||
* @return the {@link User.UserBuilder} for method chaining (i.e. to populate
|
|
||||||
* additional attributes for this user)
|
|
||||||
*/
|
|
||||||
public CustomUser.UserBuilder accountLocked(boolean accountLocked) {
|
|
||||||
this.accountLocked = accountLocked;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public CustomUserBuilder withCredentialsNonExpired(boolean credentialsNonExpired) {
|
||||||
* Defines if the credentials are expired or not. Default is false.
|
this.credentialsNonExpired = credentialsNonExpired;
|
||||||
*
|
|
||||||
* @param credentialsExpired true if the credentials are expired, false otherwise
|
|
||||||
* @return the {@link User.UserBuilder} for method chaining (i.e. to populate
|
|
||||||
* additional attributes for this user)
|
|
||||||
*/
|
|
||||||
public CustomUser.UserBuilder credentialsExpired(boolean credentialsExpired) {
|
|
||||||
this.credentialsExpired = credentialsExpired;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public CustomUserBuilder withEnabled(boolean enabled) {
|
||||||
* Defines if the account is disabled or not. Default is false.
|
this.enabled = enabled;
|
||||||
*
|
|
||||||
* @param disabled true if the account is disabled, false otherwise
|
|
||||||
* @return the {@link User.UserBuilder} for method chaining (i.e. to populate
|
|
||||||
* additional attributes for this user)
|
|
||||||
*/
|
|
||||||
public CustomUser.UserBuilder disabled(boolean disabled) {
|
|
||||||
this.disabled = disabled;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserDetails build() {
|
public CustomUserBuilder withSecret(String secret) {
|
||||||
String encodedPassword = this.passwordEncoder.apply(password);
|
this.secret = secret;
|
||||||
return new CustomUser(username, encodedPassword, !disabled, !accountExpired,
|
return this;
|
||||||
!credentialsExpired, !accountLocked, authorities);
|
}
|
||||||
|
|
||||||
|
public CustomUser build() {
|
||||||
|
CustomUser customUser = new CustomUser(username, password, !enabled, !accountNonExpired, !credentialsNonExpired, !accountNonLocked, authorities, secret);
|
||||||
|
customUser.authorities = this.authorities;
|
||||||
|
return customUser;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,26 +28,21 @@ public class CustomUserDetailService implements UserDetailsService{
|
|||||||
UserRepository userRepository;
|
UserRepository userRepository;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
|
public CustomUser loadUserByUsername(String email) throws UsernameNotFoundException {
|
||||||
//Let's split the email to get both values
|
|
||||||
String[] usernameAndCustomToken = StringUtils.split(email, String.valueOf(Character.LINE_SEPARATOR));
|
|
||||||
|
|
||||||
//if the String arrays is empty or size is not equal to 2, let's throw exception
|
final UserEntity customer = userRepository.findByEmail(email);
|
||||||
if(Objects.isNull(usernameAndCustomToken) || usernameAndCustomToken.length !=2){
|
|
||||||
throw new UsernameNotFoundException("User not found");
|
|
||||||
}
|
|
||||||
final String userName = usernameAndCustomToken[0];
|
|
||||||
final String customToken = usernameAndCustomToken[1]; // use it based on your requirement
|
|
||||||
final UserEntity customer = userRepository.findByEmail(userName);
|
|
||||||
if (customer == null) {
|
if (customer == null) {
|
||||||
throw new UsernameNotFoundException(email);
|
throw new UsernameNotFoundException(email);
|
||||||
}
|
}
|
||||||
boolean enabled = !customer.isAccountVerified(); // we can use this in case we want to activate account after customer verified the account
|
boolean enabled = !customer.isAccountVerified(); // we can use this in case we want to activate account after customer verified the account
|
||||||
UserDetails user = User.withUsername(customer.getEmail())
|
CustomUser user = CustomUser.CustomUserBuilder.aCustomUser().
|
||||||
.password(customer.getPassword())
|
withUsername(customer.getEmail())
|
||||||
.disabled(customer.isLoginDisabled())
|
.withPassword(customer.getPassword())
|
||||||
.authorities(getAuthorities(customer)).build()
|
.withEnabled(customer.isLoginDisabled())
|
||||||
;
|
.withAuthorities(getAuthorities(customer))
|
||||||
|
.withSecret(customer.getSecret())
|
||||||
|
.withAccountNonLocked(false)
|
||||||
|
.build();
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ public class CustomHeaderAuthFilter extends GenericFilterBean {
|
|||||||
|
|
||||||
var request = (HttpServletRequest) servletRequest;
|
var request = (HttpServletRequest) servletRequest;
|
||||||
var response = (HttpServletResponse)servletResponse;
|
var response = (HttpServletResponse)servletResponse;
|
||||||
|
filterChain.doFilter(servletRequest, servletResponse);
|
||||||
//if header is missing , send un-athorized error back
|
//if header is missing , send un-athorized error back
|
||||||
|
/*
|
||||||
String authHeader = request.getHeader("X-HEADER");
|
String authHeader = request.getHeader("X-HEADER");
|
||||||
if(StringUtils.isEmpty(authHeader)){
|
if(StringUtils.isEmpty(authHeader)){
|
||||||
response.setStatus(
|
response.setStatus(
|
||||||
@@ -27,6 +28,6 @@ public class CustomHeaderAuthFilter extends GenericFilterBean {
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
filterChain.doFilter(servletRequest, servletResponse);
|
filterChain.doFilter(servletRequest, servletResponse);
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.javadevjournal.core.security.mfa;
|
||||||
|
|
||||||
|
import dev.samstevens.totp.code.CodeVerifier;
|
||||||
|
import dev.samstevens.totp.code.HashingAlgorithm;
|
||||||
|
import dev.samstevens.totp.exceptions.QrGenerationException;
|
||||||
|
import dev.samstevens.totp.qr.QrData;
|
||||||
|
import dev.samstevens.totp.qr.QrGenerator;
|
||||||
|
import dev.samstevens.totp.secret.SecretGenerator;
|
||||||
|
import dev.samstevens.totp.util.Utils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
@Service("mfaTokenManager")
|
||||||
|
public class DefaultMFATokenManager implements MFATokenManager{
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SecretGenerator secretGenerator;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private QrGenerator qrGenerator;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CodeVerifier codeVerifier;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generateSecretKey() {
|
||||||
|
return secretGenerator.generate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getQRCode(String secret) throws QrGenerationException {
|
||||||
|
QrData data = new QrData.Builder().label("MFA")
|
||||||
|
.secret(secret)
|
||||||
|
.issuer("Java Development Journal")
|
||||||
|
.algorithm(HashingAlgorithm.SHA256)
|
||||||
|
.digits(6)
|
||||||
|
.period(30)
|
||||||
|
.build();
|
||||||
|
return Utils.getDataUriForImage(
|
||||||
|
qrGenerator.generate(data),
|
||||||
|
qrGenerator.getImageMimeType()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verifyTotp(String code, String secret) {
|
||||||
|
return codeVerifier.isValidCode(secret, code);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.javadevjournal.core.security.mfa;
|
||||||
|
|
||||||
|
import dev.samstevens.totp.exceptions.QrGenerationException;
|
||||||
|
|
||||||
|
public interface MFATokenManager {
|
||||||
|
|
||||||
|
String generateSecretKey();
|
||||||
|
String getQRCode(final String secret) throws QrGenerationException;
|
||||||
|
boolean verifyTotp(final String code, final String secret);
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ import java.util.Objects;
|
|||||||
|
|
||||||
public class CustomWebAuthenticationDetails extends WebAuthenticationDetails {
|
public class CustomWebAuthenticationDetails extends WebAuthenticationDetails {
|
||||||
|
|
||||||
private final String token;
|
private String token;
|
||||||
/**
|
/**
|
||||||
* Records the remote address and will also set the session Id if a session already
|
* Records the remote address and will also set the session Id if a session already
|
||||||
* exists (it won't create one).
|
* exists (it won't create one).
|
||||||
@@ -40,4 +40,12 @@ public class CustomWebAuthenticationDetails extends WebAuthenticationDetails {
|
|||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(super.hashCode(), token);
|
return Objects.hash(super.hashCode(), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToken(String token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.javadevjournal.core.security.web.authentication;
|
||||||
|
|
||||||
|
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||||
|
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class CustomWebAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CustomWebAuthenticationDetails buildDetails(HttpServletRequest context) {
|
||||||
|
return new CustomWebAuthenticationDetails(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,9 @@ public class UserEntity {
|
|||||||
private int failedLoginAttempts;
|
private int failedLoginAttempts;
|
||||||
private boolean loginDisabled;
|
private boolean loginDisabled;
|
||||||
|
|
||||||
|
private boolean mfaEnabled;
|
||||||
|
private String secret;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "user")
|
@OneToMany(mappedBy = "user")
|
||||||
private Set<SecureToken> tokens;
|
private Set<SecureToken> tokens;
|
||||||
|
|
||||||
@@ -128,6 +131,22 @@ public class UserEntity {
|
|||||||
this.loginDisabled = loginDisabled;
|
this.loginDisabled = loginDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isMfaEnabled() {
|
||||||
|
return mfaEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMfaEnabled(boolean mfaEnabled) {
|
||||||
|
this.mfaEnabled = mfaEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSecret() {
|
||||||
|
return secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecret(String secret) {
|
||||||
|
this.secret = secret;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
|||||||
@@ -6,13 +6,16 @@ import com.javadevjournal.core.exception.InvalidTokenException;
|
|||||||
import com.javadevjournal.core.exception.UnkownIdentifierException;
|
import com.javadevjournal.core.exception.UnkownIdentifierException;
|
||||||
import com.javadevjournal.core.exception.UserAlreadyExistException;
|
import com.javadevjournal.core.exception.UserAlreadyExistException;
|
||||||
import com.javadevjournal.core.security.jpa.SecureToken;
|
import com.javadevjournal.core.security.jpa.SecureToken;
|
||||||
|
import com.javadevjournal.core.security.mfa.MFATokenManager;
|
||||||
import com.javadevjournal.core.security.token.SecureTokenService;
|
import com.javadevjournal.core.security.token.SecureTokenService;
|
||||||
import com.javadevjournal.core.security.token.repository.SecureTokenRepository;
|
import com.javadevjournal.core.security.token.repository.SecureTokenRepository;
|
||||||
import com.javadevjournal.core.user.jpa.data.Group;
|
import com.javadevjournal.core.user.jpa.data.Group;
|
||||||
import com.javadevjournal.core.user.jpa.data.UserEntity;
|
import com.javadevjournal.core.user.jpa.data.UserEntity;
|
||||||
import com.javadevjournal.core.user.jpa.repository.UserGroupRepository;
|
import com.javadevjournal.core.user.jpa.repository.UserGroupRepository;
|
||||||
import com.javadevjournal.core.user.jpa.repository.UserRepository;
|
import com.javadevjournal.core.user.jpa.repository.UserRepository;
|
||||||
|
import com.javadevjournal.web.data.user.MfaTokenData;
|
||||||
import com.javadevjournal.web.data.user.UserData;
|
import com.javadevjournal.web.data.user.UserData;
|
||||||
|
import dev.samstevens.totp.exceptions.QrGenerationException;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
@@ -21,33 +24,37 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import javax.mail.MessagingException;
|
import javax.mail.MessagingException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@Service("userService")
|
@Service("userService")
|
||||||
public class DefaultUserService implements UserService{
|
public class DefaultUserService implements UserService{
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
private UserRepository userRepository;
|
private UserRepository userRepository;
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
private PasswordEncoder passwordEncoder;
|
private PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
private EmailService emailService;
|
private EmailService emailService;
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
private SecureTokenService secureTokenService;
|
private SecureTokenService secureTokenService;
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
SecureTokenRepository secureTokenRepository;
|
SecureTokenRepository secureTokenRepository;
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
UserGroupRepository groupRepository;
|
UserGroupRepository groupRepository;
|
||||||
|
|
||||||
@Value("${site.base.url.https}")
|
@Value("${site.base.url.https}")
|
||||||
private String baseURL;
|
private String baseURL;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private MFATokenManager mfaTokenManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register(UserData user) throws UserAlreadyExistException {
|
public void register(UserData user) throws UserAlreadyExistException {
|
||||||
if(checkIfUserExist(user.getEmail())){
|
if(checkIfUserExist(user.getEmail())){
|
||||||
@@ -57,6 +64,7 @@ public class DefaultUserService implements UserService{
|
|||||||
BeanUtils.copyProperties(user, userEntity);
|
BeanUtils.copyProperties(user, userEntity);
|
||||||
encodePassword(user, userEntity);
|
encodePassword(user, userEntity);
|
||||||
updateCustomerGroup(userEntity);
|
updateCustomerGroup(userEntity);
|
||||||
|
userEntity.setSecret(mfaTokenManager.generateSecretKey());
|
||||||
userRepository.save(userEntity);
|
userRepository.save(userEntity);
|
||||||
sendRegistrationConfirmationEmail(userEntity);
|
sendRegistrationConfirmationEmail(userEntity);
|
||||||
|
|
||||||
@@ -67,6 +75,7 @@ public class DefaultUserService implements UserService{
|
|||||||
userEntity.addUserGroups(group);
|
userEntity.addUserGroups(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkIfUserExist(String email) {
|
public boolean checkIfUserExist(String email) {
|
||||||
return userRepository.findByEmail(email)!=null ? true : false;
|
return userRepository.findByEmail(email)!=null ? true : false;
|
||||||
@@ -83,7 +92,7 @@ public class DefaultUserService implements UserService{
|
|||||||
emailContext.buildVerificationUrl(baseURL, secureToken.getToken());
|
emailContext.buildVerificationUrl(baseURL, secureToken.getToken());
|
||||||
try {
|
try {
|
||||||
emailService.sendMail(emailContext);
|
emailService.sendMail(emailContext);
|
||||||
} catch (MessagingException e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,6 +126,16 @@ public class DefaultUserService implements UserService{
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MfaTokenData mfaSetup(String email) throws UnkownIdentifierException, QrGenerationException {
|
||||||
|
UserEntity user= userRepository.findByEmail(email);
|
||||||
|
if(user == null ){
|
||||||
|
// we will ignore in case account is not verified or account does not exists
|
||||||
|
throw new UnkownIdentifierException("unable to find account or account is not active");
|
||||||
|
}
|
||||||
|
return new MfaTokenData( mfaTokenManager.getQRCode( user.getSecret()), user.getSecret());
|
||||||
|
}
|
||||||
|
|
||||||
private void encodePassword(UserData source, UserEntity target){
|
private void encodePassword(UserData source, UserEntity target){
|
||||||
target.setPassword(passwordEncoder.encode(source.getPassword()));
|
target.setPassword(passwordEncoder.encode(source.getPassword()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import com.javadevjournal.core.exception.InvalidTokenException;
|
|||||||
import com.javadevjournal.core.exception.UnkownIdentifierException;
|
import com.javadevjournal.core.exception.UnkownIdentifierException;
|
||||||
import com.javadevjournal.core.exception.UserAlreadyExistException;
|
import com.javadevjournal.core.exception.UserAlreadyExistException;
|
||||||
import com.javadevjournal.core.user.jpa.data.UserEntity;
|
import com.javadevjournal.core.user.jpa.data.UserEntity;
|
||||||
|
import com.javadevjournal.web.data.user.MfaTokenData;
|
||||||
import com.javadevjournal.web.data.user.UserData;
|
import com.javadevjournal.web.data.user.UserData;
|
||||||
|
import dev.samstevens.totp.exceptions.QrGenerationException;
|
||||||
|
|
||||||
public interface UserService {
|
public interface UserService {
|
||||||
|
|
||||||
@@ -13,4 +15,5 @@ public interface UserService {
|
|||||||
void sendRegistrationConfirmationEmail(final UserEntity user);
|
void sendRegistrationConfirmationEmail(final UserEntity user);
|
||||||
boolean verifyUser(final String token) throws InvalidTokenException;
|
boolean verifyUser(final String token) throws InvalidTokenException;
|
||||||
UserEntity getUserById(final String id) throws UnkownIdentifierException;
|
UserEntity getUserById(final String id) throws UnkownIdentifierException;
|
||||||
|
MfaTokenData mfaSetup(final String email) throws UnkownIdentifierException, QrGenerationException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
package com.javadevjournal.web.controller.user;
|
package com.javadevjournal.web.controller.user;
|
||||||
|
|
||||||
import com.javadevjournal.core.exception.InvalidTokenException;
|
import com.javadevjournal.core.exception.InvalidTokenException;
|
||||||
|
import com.javadevjournal.core.exception.UnkownIdentifierException;
|
||||||
import com.javadevjournal.core.exception.UserAlreadyExistException;
|
import com.javadevjournal.core.exception.UserAlreadyExistException;
|
||||||
import com.javadevjournal.core.user.service.UserService;
|
import com.javadevjournal.core.user.service.UserService;
|
||||||
|
import com.javadevjournal.web.data.user.MfaTokenData;
|
||||||
import com.javadevjournal.web.data.user.UserData;
|
import com.javadevjournal.web.data.user.UserData;
|
||||||
|
import dev.samstevens.totp.exceptions.QrGenerationException;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.MessageSource;
|
||||||
@@ -17,6 +20,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
import static com.javadevjournal.ApplicationConstant.REDIRECT;
|
import static com.javadevjournal.ApplicationConstant.REDIRECT;
|
||||||
@@ -27,10 +31,10 @@ public class RegistrationController {
|
|||||||
|
|
||||||
private static final String REDIRECT_LOGIN= "redirect:/login";
|
private static final String REDIRECT_LOGIN= "redirect:/login";
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
private UserService userService;
|
private UserService userService;
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
private MessageSource messageSource;
|
private MessageSource messageSource;
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
@@ -47,7 +51,11 @@ public class RegistrationController {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
userService.register(userData);
|
userService.register(userData);
|
||||||
}catch (UserAlreadyExistException e){
|
MfaTokenData mfaData = userService.mfaSetup(userData.getEmail());
|
||||||
|
model.addAttribute("qrCode", mfaData.getQrCode());
|
||||||
|
model.addAttribute("qrCodeKey", mfaData.getMfaCode());
|
||||||
|
model.addAttribute("qrCodeSetup", true);
|
||||||
|
}catch (UserAlreadyExistException | QrGenerationException | UnkownIdentifierException e){
|
||||||
bindingResult.rejectValue("email", "userData.email","An account already exists for this email.");
|
bindingResult.rejectValue("email", "userData.email","An account already exists for this email.");
|
||||||
model.addAttribute("registrationForm", userData);
|
model.addAttribute("registrationForm", userData);
|
||||||
return "account/register";
|
return "account/register";
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.javadevjournal.web.data.user;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class MfaTokenData implements Serializable {
|
||||||
|
|
||||||
|
private String qrCode;
|
||||||
|
private String mfaCode;
|
||||||
|
|
||||||
|
public MfaTokenData() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getQrCode() {
|
||||||
|
return qrCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQrCode(String qrCode) {
|
||||||
|
this.qrCode = qrCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMfaCode() {
|
||||||
|
return mfaCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMfaCode(String mfaCode) {
|
||||||
|
this.mfaCode = mfaCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MfaTokenData(String qrCode, String mfaCode) {
|
||||||
|
this.qrCode = qrCode;
|
||||||
|
this.mfaCode = mfaCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -63,3 +63,9 @@ jdj.security.failedlogin.count =2
|
|||||||
jdj.brute.force.cache.max=1000
|
jdj.brute.force.cache.max=1000
|
||||||
|
|
||||||
|
|
||||||
|
###### Spring LDAP configuration. This is using Apache DS server but you can use it for any other LDAP server
|
||||||
|
#spring.ldap.embedded.ldif=classpath:users.ldif
|
||||||
|
#spring.ldap.embedded.base-dn=dc=springframework,dc=org
|
||||||
|
#spring.ldap.embedded.port=53389
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ login.error= Username or password is incorrect. Please make sure to provide vali
|
|||||||
user.registration.verification.missing.token= Token is empty. Please make sure to copy the entire URL
|
user.registration.verification.missing.token= Token is empty. Please make sure to copy the entire URL
|
||||||
user.registration.verification.invalid.token= It seems that token is expired or has been modified.Please provide a valid token.
|
user.registration.verification.invalid.token= It seems that token is expired or has been modified.Please provide a valid token.
|
||||||
user.registration.verification.success= Thanks for the account verification. You can now login to your account.
|
user.registration.verification.success= Thanks for the account verification. You can now login to your account.
|
||||||
user.registration.verification.email.msg= Thanks for your registration. We have sent a verification email. Please verify your account.
|
user.registration.verification.email.msg= Thanks for your registration. We have sent a verification email. Please verify your account.Please scan the QR code for generating MFA token for login.
|
||||||
user.forgotpwd.msg= If the email address entered matches your account, you will receive an email with a link to reset your password.
|
user.forgotpwd.msg= If the email address entered matches your account, you will receive an email with a link to reset your password.
|
||||||
user.password.updated.msg= Your password is updated. Please login
|
user.password.updated.msg= Your password is updated. Please login
|
||||||
user.account.locked = Your account has been locked due to multiple failed login attempts.
|
user.account.locked = Your account has been locked due to multiple failed login attempts.
|
||||||
@@ -18,10 +18,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
|
|
||||||
<div class="card-body register-card-body">
|
<div class="card-body register-card-body">
|
||||||
<div class="alert alert-success" role="alert" th:if="${registrationMsg != null}">
|
<div class="alert alert-success" role="alert" th:if="${registrationMsg != null}">
|
||||||
<p th:text="${registrationMsg}"></p>
|
<p th:text="${registrationMsg}"></p>
|
||||||
</div>
|
</div>
|
||||||
|
<div th:if="${registrationMsg != null}">
|
||||||
|
<img class="col-md-12" th:src="${qrCode}" />
|
||||||
|
<p th:text="${qrCodeKey}"></p>
|
||||||
|
</div>
|
||||||
|
<div th:if="${registrationMsg == null}">
|
||||||
<p class="login-box-msg">Register a new account</p>
|
<p class="login-box-msg">Register a new account</p>
|
||||||
<form action="#" th:action="@{/register}" th:object="${userData}" method="post">
|
<form action="#" th:action="@{/register}" th:object="${userData}" method="post">
|
||||||
<div class="alert alert-danger" th:if="${#fields.hasErrors('*')}">
|
<div class="alert alert-danger" th:if="${#fields.hasErrors('*')}">
|
||||||
@@ -90,7 +96,7 @@
|
|||||||
<!-- /.col -->
|
<!-- /.col -->
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
<a href="login" class="text-center">I already have an Account</a>
|
<a href="login" class="text-center">I already have an Account</a>
|
||||||
</div>
|
</div>
|
||||||
<!-- /.form-box -->
|
<!-- /.form-box -->
|
||||||
|
|||||||
Reference in New Issue
Block a user