English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Вход и выход в Spring Angular

В этом разделе мы создадим веб-приложение для входа в систему и выхода из системы. Приложение включает в себя формы регистрации и входа. В этой интеграции мы используем Spring для обработки части бэкенда, а Angular для обработки части фронта.

Рабочее приложение

После того как мы部署ли приложение на сервер, будет создана стартовая страница, содержащая две ссылки - «Регистрация» и «Вход».Новые пользователи могут зарегистрироваться, заполнив необходимые详细信息.Однако существующие пользователи могут входить в систему с использованием своего email ID и пароля.После входа в систему мы можем получить详细信息 о существующих пользователях.В конце мы можем выйти из текущего состояния, нажав на ссылку «Выйти».

Используемые инструменты

Используйте любую IDE для разработки Spring и Hibernate проектов. Это может быть MyEclipse/Eclipse/Netbeans. Здесь мы используем Eclipse.Для базы данных используется MySQL.Используйте любую IDE для разработки Angular проекта. Это может быть Visual Studio Code/Sublime. Здесь мы используем Visual Studio Code.Сервер: Apache Tomcat/JBoss/Glassfish/Weblogic/Websphere.

Используемые нами технологии

Здесь мы используем следующие технологии:

Spring5 Hibernate5 Angular6 MYSQL

Создание базы данных

Давайте создадим базу данных loginlogoutexample Не нужно создавать таблицы, так как Hibernate автоматически создаст их.

Модуль Spring

Давайте посмотрим на структуру каталогов Spring, которые нам нужно будет следовать:

Чтобы разработать приложение для входа в систему и выхода из системы, следуйте следующим шагам: -

Добавьте зависимость в файл pom.xml.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.w3codebox</groupId>
  <artifactId>LoginLogoutExample</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>LoginLogoutExample Maven Webapp</name>
  <url>http://maven.apache.org</url>
  
  
  	<properties>
		<springframework.version>5.0.6.RELEASE</springframework.version>
		<hibernate.version>5.2.16.Final</hibernate.version>
		<mysql.connector.version>5.1.45</mysql.connector.version>
		<c3po.version>0.9.5.2</c3po.version>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
	</properties>
  
  
  <dependencies>
  
  <!-- Spring -->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-webmvc</artifactId>
		<version>${springframework.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-tx</artifactId>
		<version>${springframework.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-orm</artifactId>
		<version>${springframework.version}</version>
	</dependency>
	<!-- Добавить Jackson для конвертеров JSON -->
	<dependency>
		<groupId>com.fasterxml.jackson.core</groupId>
		<artifactId>jackson-databind</artifactId>
		<version>2.9.5</version>
	</dependency>
	<!-- Hibernate -->
	<dependency>
		<groupId>org.hibernate</groupId>
		<artifactId>hibernate-core</artifactId>
		<version>${hibernate.version}</version>
	</dependency>
	<!-- MySQL -->
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>${mysql.connector.version}</version>
	</dependency>
	<!-- C3PO -->
	<dependency>
		<groupId>com.mchange</groupId>
		<artifactId>c3p0</artifactId>
		<version>${c3po.version}</version>
	</dependency>
	<!-- Servlet+JSP+JSTL -->
	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>javax.servlet-api</artifactId>
		<version>3.1.0</version>
	</dependency>
	<dependency>
		<groupId>javax.servlet.jsp</groupId>
		<artifactId>javax.servlet.jsp-api</artifactId>
		<version>2.3.1</version>
	</dependency>
	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>jstl</artifactId>
		<version>1.2</version>
	</dependency>
	<!-- to compensate for java 9 not including jaxb -->
	<dependency>
		<groupId>javax.xml.bind</groupId>
		<artifactId>jaxb-api</artifactId>
		<version>2.3.0</version>
	</dependency>
	<!--  Web token dependency -->
    <dependency>
    	<groupId>io.jsonwebtoken</groupId>
    	<artifactId>jjwt</artifactId>
    	<version>0.9.1</version>
	</dependency>
	 	
 	<!-- JUnit dependency -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>
    
	<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
	<dependency>
	    <groupId>org.apache.commons</groupId>
	    <artifactId>commons-dbcp2</artifactId>
	    <version>2.0</version>
	</dependency> 
  </dependencies>
  
  
  <build>
    <finalName>LoginLogoutExample</finalName>
  </build>
</project>

Создание класса конфигурации
Мы выполняем конфигурацию на основе комментариев, а не XML. Поэтому мы создаем два класса и в них указываем необходимую конфигурацию.

DemoAppConfig.java

package com.w3codebox.LoginLogoutExample.config;
import java.beans.PropertyVetoException;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.mchange.v2.c3p0.ComboPooledDataSource;
@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan("com.w3codebox.LoginLogoutExample")
@PropertySource(value = {"classpath:persistence-mysql.properties"})
@PropertySource(value = {"classpath:persistence-mysql.properties"})
@PropertySource(value = {"classpath:application.properties"})
public class DemoAppConfig implements WebMvcConfigurer {
	@Autowired
	private Environment env;
	@Bean
	public DataSource myDataSource() {
		// создайте пул подключений
		ComboPooledDataSource myDataSource = new ComboPooledDataSource();
		// установите jdbc драйвер
		try
			myDataSource.setDriverClass("com.mysql.jdbc.Driver");		
		}
		catch (PropertyVetoException exc) {
			throw new RuntimeException(exc);
		}
		// set database connection props
		myDataSource.setJdbcUrl(env.getProperty("jdbc.url"));
		myDataSource.setUser(env.getProperty("jdbc.user"));
		myDataSource.setPassword(env.getProperty("jdbc.password"));
		// set connection pool props
		myDataSource.setInitialPoolSize(getIntProperty("connection.pool.initialPoolSize"));
		myDataSource.setMinPoolSize(getIntProperty("connection.pool.minPoolSize"));
		myDataSource.setMaxPoolSize(getIntProperty("connection.pool.maxPoolSize"));		
		myDataSource.setMaxIdleTime(getIntProperty("connection.pool.maxIdleTime"));
		return myDataSource;
	}
	private Properties getHibernateProperties() {
		// set hibernate properties
		Properties props = new Properties();
		props.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
		props.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
		props.setProperty("hibernate.format_sql", env.getProperty("hibernate.format_sql"));
		props.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl"));
		return props;				
	}
	// необходима вспомогательная функция 
		// чтение свойств окружения и преобразование в int
		private int getIntProperty(String propName) {
			String propVal = env.getProperty(propName);
			// теперь конвертируйте в int
			int intPropVal = Integer.parseInt(propVal);
			return intPropVal;
		}
		@Bean
		public LocalSessionFactoryBean sessionFactory(){
			// создать сессию factory
			LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
			// установить свойства
			sessionFactory.setDataSource(myDataSource());
			sessionFactory.setPackagesToScan(env.getProperty("hibernate.packagesToScan"));
			sessionFactory.setHibernateProperties(getHibernateProperties());
			return sessionFactory;
		}
		@Bean
		@Autowired
		public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
			// настройка менеджера транзакций на основе сессии factory
			HibernateTransactionManager txManager = new HibernateTransactionManager();
			txManager.setSessionFactory(sessionFactory);
			return txManager;
		}	
}

MySpringMvcDispatcherServletInitializer.java

package com.w3codebox.LoginLogoutExample.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class MySpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
	@Override
	protected Class<?>[] getRootConfigClasses() {
		// Todo Автоматически сгенерированный метод шаблона
		return null;
	}
	@Override
	protected Class<?>[] getServletConfigClasses() {
		return new Class[] { DemoAppConfig.class };
	}
	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}
}

Создание класса сущности
Здесь мы создадим следующие классы сущностей: AdminDetail.java - это класс Entity/POJO (обычный старый объект Java). Token.java - для аутентификации.

AdminDetail.java

package com.w3codebox.LoginLogoutExample.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="admin_detail")
public class AdminDetail {
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	@Column(name="admin_id")
	private int adminID;
	@Column(name="email_id", unique=true)
	public String emailId;
	@Column(name="name")
	public String name;
	@Column(name="password")
	public String password;
	@Column(name="role")
	public String role;
	public AdminDetail() { }
	public AdminDetail(int adminID, String emailId, String name, String password, String role) {
		super();
		this.adminID = adminID;
		this.emailId = emailId;
		this.name = name;
		this.password = password;
		this.role = role;
	}
	public int getAdminID() {
		return adminID;
	}
	public void setAdminID(int adminID) {
		this.adminID = adminID;
	}
	public String getEmailId() {
		return emailId;
	}
	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getRole() {
		return role;
	}
	public void setRole(String role) {
		this.role = role;
	}
	@Override
	public String toString() {
		return "AdminDetail [adminID=": + adminID + ", emailId=": + emailId + ", name=": + name + ", password=": + password
				+ ", role=" + role + "]";
	}
}

Token.java

package com.w3codebox.LoginLogoutExample.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="Token")
public class Token {
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	@Column(name="token_id")
	private int tokenID;
	@Column(name="user_id", unique=true)
	private int userID;
	 
	@Column(name="authenticationToken")
	private String authenticationToken;
	@Column(name="secretKey")
	private String secretKey;
	@Column(name="email_id")
	private String emailId;
	public Token() { }
	public Token(int tokenID, int userID, String authenticationToken, String secretKey, String emailId) {
		super();
		this.tokenID = tokenID;
		this.userID = userID;
		this.authenticationToken = authenticationToken;
		this.secretKey = secretKey;
		this.emailId = emailId;
	}
	public int getTokenID() {
		return tokenID;
	}
	public void setTokenID(int tokenID) {
		this.tokenID = tokenID;
	}
	public int getUserID() {
		return userID;
	}
	public void setUserID(int userID) {
		this.userID = userID;
	}
	public String getAuthenticationToken() {
		return authenticationToken;
	}
	public void setAuthenticationToken(String authenticationToken) {
		this.authenticationToken = authenticationToken;
	}
	public String getSecretKey() {}}
		return secretKey;
	}
	public void setSecretKey(String secretKey) {
		this.secretKey = secretKey;
	}
	public String getEmailId() {
		return emailId;
	}
	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}
	@Override
	public String toString() {
		return \
				+ ", secretKey=" + secretKey + ", emailId=" + emailId + "]";
	}
}

Создание интерфейса DAO
Здесь мы создадим два интерфейса DAO для выполнения операций, связанных с базой данных.

AdminDAO.java

package com.w3codebox.LoginLogoutExample.DAO.interfaces;
import java.util.List;
import com.w3codebox.LoginLogoutExample.entity.AdminDetail;
public interface AdminDAO {
	public int saveAdminDetail(AdminDetail adminDetail);
	public int adminLogin(String emailId, String password);
	public List<AdminDetail> getAdminData();
}

TokenDAO.java

package com.w3codebox.LoginLogoutExample.DAO.interfaces;
public interface TokenDAO {
	public void saveUserEmail(String email, int adminId);
	public boolean updateToken(String email, String authenticationToken, String secretKey);
	public int getTokenDetail(String email);
	public int tokenAuthentication(String token, int emailId);
}

Создание класса реализации интерфейса DAO

AdminDAOImpl.java

package com.w3codebox.LoginLogoutExample.DAO.implementation;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.w3codebox.LoginLogoutExample.DAO.interfaces.AdminDAO;
import com.w3codebox.LoginLogoutExample.entity.AdminDetail;
@Repository("adminDAO")
public class AdminDAOImpl implements AdminDAO {
	// Автоматически внедрить SessionFactory объект, чтобы мы могли получить объект session для взаимодействия с базой данных.
	@Autowired
	private SessionFactory sessionFactory;
	/*
	 * Регистрация подробностей администратора. 
	*/
	public int saveAdminDetail(AdminDetail adminDetail) {
		Session session = null;
		try
		{
			session = sessionFactory.getCurrentSession();
			int id = (Integer) session.save(adminDetail);
			return id;
		}
		catch(Exception exception)
		{
			System.out.println("Exception while saving admin Details: " + exception.getMessage());
			return 0;
		}
		finally
		{
			session.flush();
		}
	}
	public int adminLogin(String emailId, String password) {
		Session session = null;
		try
		{
			session = sessionFactory.getCurrentSession();
			Query query = session.createQuery("from AdminDetail where emailId=:emailId and password=:password");
			query.setParameter("emailId", emailId);
			query.setParameter("password", password);
			List<AdminDetail> list = query.list();
			int size = list.size();
			if(size == 1)
			{
				return list.get(0).getAdminID();
			}
			else
			{
				return -1;
			}
		}
		catch(Exception exception)
		{
			System.out.println("Exception while saving admin Details: " + exception.getMessage());
			return 0;
		}
		finally
		{
			session.flush();
		}
	}
	public List<AdminDetail> getAdminData() {
		Session session = null;
		try
		{
			session = sessionFactory.getCurrentSession();
			Query<AdminDetail> query = session.createQuery("from AdminDetail");
			List<AdminDetail> list = query.list();
			if(list.size() > 0)
			{
				return list;
			}
			else
			{
				return null;
			}
		}
		catch(Exception exception)
		{
			System.out.println("Exception while saving admin Details: " + exception.getMessage());
			return null;
		}
		finally
		{
			session.flush();
		}
	}
}

TokenDAOImpl.java

package com.w3codebox.LoginLogoutExample.DAO.implementation;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.w3codebox.LoginLogoutExample.DAO.interfaces.TokenDAO;
import com.w3codebox.LoginLogoutExample.entity.Token;
@Repository("tokenDAO")
public class TokenDAOImpl implements TokenDAO {
	@Autowired
	SessionFactory sessionFactory;
	public void saveUserEmail(String email, int adminId) {
		Session session = null; 
		try
		{
			session = sessionFactory.getCurrentSession();
			Токен t = new Токен();
			t.setUserID(adminId);
			t.setEmailId(email);
			session.save(t); 
		}
		catch(Exception exception)
		{
			System.out.println("Exception in saving UserEmail In Token Table :: " + exception.getMessage());
		}
		finally
		{
			session.flush();
		}
	}
	public boolean updateToken(String email, String authenticationToken, String secretKey) {
		Session session = null;
		try 
		{
			session = sessionFactory.getCurrentSession();
			Query theQuery = null;		
			theQuery = session.createQuery("Update Token set authenticationToken = :authenticationToken, secretKey = :secretKey where emailId = :userEmail ");
			theQuery.setParameter("authenticationToken", authenticationToken);
			theQuery.setParameter("userEmail", email);
			theQuery.setParameter("secretKey", secretKey);
			int result = theQuery.executeUpdate();
			if(result == 1)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		catch(Exception exception)
		{
			System.out.println("Error while updating token :: " + exception.getMessage());
			return false;
		}
		finally
		{
			session.flush();
		}			
	}
	public int getTokenDetail(String email) {
		Session session = null;
		try
		{
			session = sessionFactory.getCurrentSession();
			Query<Token> query = session.createQuery("from Token where emailId = :userEmail");
			query.setParameter("userEmail", email);
			List<Token> tokenDetails = query.list();
			if(tokenDetails.size() > 0)
			{
				return tokenDetails.get(0).getTokenID();
			}
			else
			{
				return 0;
			}
		}
		catch(Exception exception)
		{
			System.out.println("Exception while getting token ID :: " + exception.getMessage());		
		}
		finally
		{
			session.flush();
		}
		return 0;
	}
	public int tokenAuthentication(String token, int emailId) {
		Session session = null;
		try 
		{
			session = sessionFactory.getCurrentSession();
			Query query = session.createQuery("from Token where userID = :userID and authenticationToken = :token");
			query.setParameter("userID", emailId);
			query.setParameter("token", token);
			List<Token> tokenDetails = query.list();
			if(tokenDetails.size() > 0)
			{
				return tokenDetails.get(0).getTokenID();
			}
			else
			{
				return 0;
			}
		}
		catch(Exception exception)
		{
			System.out.println("Exception while Authenticating token :: " + exception);
			return 0;
		}
		finally
		{
			session.flush();
		}
	}
}

Создание интерфейса сервисного уровня

Здесь мы создаем сервисный интерфейс, который служит мостом между классами DAO и Entity.

AdminService.java

package com.w3codebox.LoginLogoutExample.service.interfaces;
import java.util.List;
import com.w3codebox.LoginLogoutExample.entity.AdminDetail;
public interface AdminService {
	public int saveAdminDetail(AdminDetail adminDetail);
	public int adminLogin(String emailId, String password);
	public List<AdminDetail> getAdminData();
}

TokenService.java

package com.w3codebox.LoginLogoutExample.service.interfaces;
public interface TokenService {
	public void saveUserEmail(String email, int adminId);
	public boolean updateToken(String email, String authenticationToken, String secretKey);
	public int getTokenDetail(String email);
	public int tokenAuthentication(String token, int emailId);
}

создание класса реализации сервисного уровня

AdminServiceImpl.java

package com.w3codebox.LoginLogoutExample.service.implementation;
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.w3codebox.LoginLogoutExample.DAO.interfaces.AdminDAO;
import com.w3codebox.LoginLogoutExample.entity.AdminDetail;
import com.w3codebox.LoginLogoutExample.service.interfaces.AdminService;
@Service("adminService")
public class AdminServiceImpl implements AdminService {
	@Autowired
	private AdminDAO adminDAO;
	@Transactional
	public int saveAdminDetail(AdminDetail adminDetail) {
		return adminDAO.saveAdminDetail(adminDetail);
	}
	@Transactional
	public int adminLogin(String emailId, String password) {
		return adminDAO.adminLogin(emailId, password);
	}
	@Transactional
	public List<AdminDetail> getAdminData() {
		return adminDAO.getAdminData();
	}
}

TokenServiceImpl.java

package com.w3codebox.LoginLogoutExample.service.implementation;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.w3codebox.LoginLogoutExample.DAO.interfaces.TokenDAO;
import com.w3codebox.LoginLogoutExample.service.interfaces.TokenService;
@Service("tokenService")
public class TokenServiceImpl implements TokenService {
	@Autowired
	private TokenDAO tokenDAO;
	@Transactional
	public void saveUserEmail(String email, int adminId) {
		tokenDAO.saveUserEmail(email, adminId);
	}
	@Transactional
	public boolean updateToken(String email, String authenticationToken, String secretKey) {
		return tokenDAO.updateToken(email, authenticationToken, secretKey);
	}
	@Transactional
	public int getTokenDetail(String email) {
		return tokenDAO.getTokenDetail(email);
	}
	@Transactional
	public int tokenAuthentication(String token, int emailId) {
		return tokenDAO.tokenAuthentication(token, emailId);
	}
}

创建令牌类

GenerateToken.java

package com.javavtpoint.LoginLogoutExample.Token;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Date;
import java.util.Random;
import io.jsonwebtoken.*;
public class GenerateToken {
public String[] createJWT(String id, String issuer, String subject, String role, long ttlMillis) {
	    //The JWT signature algorithm we will be using to sign the token
	    SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
	 
	    long nowMillis = System.currentTimeMillis();
	    Date now = new Date(nowMillis);
	    
		Random random = new Random();
		String secretKey = id + Integer.toString(random.nextInt(1000));
	    byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(secretKey);
	    
	    Key signingKey = null;
	    try{
	    	
	    	signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
	    }
	    catch(Exception e)
	    {
	    	System.out.println("Exception while generating key " + e.getMessage() );
	    }
	    
	    JwtBuilder builder = Jwts.builder().setId(id)
	                                .setIssuedAt(now)
	                                .setSubject(subject)
	                                .setIssuer(issuer)
	                                .setPayload(role)
	                                .signWith(signatureAlgorithm, signingKey);
	    
	    //if it has been specified, let's add the expiration
	    if (ttlMillis >= 0) {
	    long expMillis = nowMillis + ttlMillis;
	        Date exp = new Date(expMillis);
	        builder.setExpiration(exp);
	    }
	    
	    String[] tokenInfo = {builder.compact() , secretKey};
	    return tokenInfo;
	    
	}
}

Создание класса контроллера

AdminController.java

package com.w3codebox.LoginLogoutExample.restController;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.w3codebox.LoginLogoutExample.entity.AdminDetail;
import com.w3codebox.LoginLogoutExample.service.interfaces.AdminService;
import com.w3codebox.LoginLogoutExample.service.interfaces.TokenService;
import com.javavtpoint.LoginLogoutExample.Token.GenerateToken;
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://localhost:4200", allowedHeaders = "*", exposedHeaders = "Authorization")
public class AdminController {
	@Autowired
	private AdminService adminService;
	@Autowired
	private TokenService tokenService;
	GenerateToken generateToken = new GenerateToken();
	@PostMapping("/saveAdmin")
	public int saveAdminDetail(@RequestBody AdminDetail adminDetail) {
		return adminService.saveAdminDetail(adminDetail);
	}
	@PostMapping("/login")
	public ResponseEntity<Integer> login(@RequestBody AdminDetail adminDetail)
	{
		int status;
		HttpHeaders httpHeader = null;
		// Аутентифицировать пользователя.
		status = adminService.adminLogin(adminDetail.getEmailId(), adminDetail.getPassword());
		/*
		 * Если пользователь аутентифицирован, выполнить задачу авторизации.
		 */
		if (status > 0) 
		{
			/*
			 * Создать токен.
			 */
			String tokenData[] = generateToken.createJWT(adminDetail.getEmailId(), "w3codebox", "JWT Token",
					adminDetail.getRole(), 43200000);
			// Получить токен.
			String token = tokenData[0];
			System.out.println("Авторизация :: " + token);
			// Создайте объект заголовка.
			httpHeader = new HttpHeaders();
			// Добавьте токен в заголовок.
			httpHeader.add("Authorization", token);
			// Проверьте, существует ли токен.
			long isUserEmailExists = tokenService.getTokenDetail(adminDetail.getEmailId());
			/*
			 * Если токен существует, обновите токен,否则 создайте и вставьте токен.
			 */
			if (isUserEmailExists > 0) 
			{
				tokenService.updateToken(adminDetail.getEmailId(), token, tokenData[1]);
			} 
			else 
			{
				tokenService.saveUserEmail(adminDetail.getEmailId(), status);
				tokenService.updateToken(adminDetail.getEmailId(), token, tokenData[1]);
			}
			return new ResponseEntity<Integer>(status, httpHeader, HttpStatus.OK);
		} 
		// Если не аутентифицирован, вернем status, который мы получили.
		else 
		{
			return new ResponseEntity<Integer>(status, httpHeader, HttpStatus.OK);
		}
	}
	@GetMapping("/getAdminData/{adminId}")
	public List<AdminDetail> getAdminData(@PathVariable int adminId, @RequestHeader("Authorization") String authorizationToken)
	{
		String[] token = authorizationToken.split(" ");
		int result = tokenService.tokenAuthentication(token[1], adminId);
		if (result > 0) {
			return adminService.getAdminData();
		}
			return null;
		}
	}
}

Создание файла свойств

Здесь мы занимаемся проектом src/main/resources в файле создайте файл свойств. Следующие файлы содержат конфигурацию соединений Hibernate.

persistence-mysql.properties

## Свойства JDBC-соединения
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/loginlogoutexample?useSSL=false
jdbc.user=root
jdbc.password=
## Свойства пула соединений
connection.pool.initialPoolSize=5
connection.pool.minPoolSize=5
connection.pool.maxPoolSize=20
connection.pool.maxIdleTime=3000
## Свойства Hibernate
<!-- hibernate.dialect=org.hibernate.dialect.MySQLDialect -->
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.hbm2ddl=update
hibernate.packagesToScan=com.w3codebox.LoginLogoutExample.entity

Модуль Angular

Давайте посмотрим на структуру каталогов Angular:

Создание проекта Angular

Давайте используем следующие команды для создания проекта Angular:

Здесь LoginLogoutExample - это имя

Установка CSS-фреймворка Bootstrap

Используйте следующие команды для установки Bootstrap в проекте.

npm install bootstrap @ 3.3.7 --save

Теперь в файле style.css включите следующий код.

@import \

Генерация компонента
Откройте проект в Visual Studio и затем используйте следующие команды для генерации следующих компонентов Angular:
ng gc домашняя страница
ng gc вход
ng gc регистрация
ng gc конфигурационный файл

Мы также используем следующие команды для создания класса сервиса: -

ng gs services/Admin

Редактировать app.module.ts Файл реализацию маршрутизации- Здесь мы будем импортировать @angular/router в пакете RouterModule и определяем путь в массиве imports. Импортируем ReactiveFormsModule - Здесь мы будем импортировать ReactiveFormsModule для реактивных форм и указываем его в массиве imports. Импортируем HttpModule - Здесь мы импортируем HttpModule и указываем его в массиве import. Регистрация класса сервиса- Здесь мы упоминаем класс сервиса в массиве провайдеров.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
// import Http module
import { HttpModule} from '@angular/http';
// import ReactiveFormsModule for reactive form
import { ReactiveFormsModule } from '@angular/forms';
// import module for Routing.
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
import { HomeComponent } from './home/home.component';
import { SignupComponent } from './signup/signup.component';
import { AdminService } from './services/admin.service';
import { ProfileComponent } from './profile/profile.component';
@NgModule({
  declarations: [
    AppComponent,
    LoginComponent,
    HomeComponent,
    SignupComponent,
    ProfileComponent
  ],
  imports: [
    BrowserModule,
    ReactiveFormsModule,
    HttpModule,
    RouterModule.forRoot([
      {
        path : '',
        component : HomeComponent 
      },
      {
        path : 'login',
        component : LoginComponent  
      },
      {
        path : 'signup',
        component : SignupComponent 
      },
      {
        path : 'profile/:adminId',
        component : ProfileComponent
      }
    ])
  ],
  providers: [
    AdminService
  ],
  bootstrap: [AppComponent]
})}}
export class AppModule { }

Редактировать app.component.html Файл

<router-outlet></router-outlet>

Редактировать home.component.html Файл
Это страница приветствия приложения, которая включает два ссылки - "регистрация" и "вход".

<div style="text-align: center">
    <h2>  <a [routerLink]="['/signup']">SignUp</a> <br><br> </h2>
    <h2>  <a [routerLink]="['/login']">Login</a> <br><br> </h2>
    
</div>

создание AdminDetail.ts класс

Давайте создадим класс с помощью следующих команд: -

Теперь, в AdminDetail в классе указать обязательные поля.

export class AdminDetail {
    emailId : string;
    name : string;
    password : string ;
    role : string;
}

Цель этого класса - выполнить маппинг указанных полей к полям класса Spring entity.

Редактировать admin.service.ts Файл

import { Injectable } from '@angular/core';
import { Http, RequestOptions, Headers } from '@angular/http';
import { Observable } from 'rxjs';
import { AdminDetail } from '../classes/admin-detail';
import { Router } from '@angular/router';
import { JwtHelperService } from '@auth0/angular-jwt';
@Injectable({
  providedIn: 'root'
})}}
export class AdminService {
  // Основной URL
  private baseUrl = "http://localhost:8080/LoginLogoutExample/api/";
  
  constructor(private http: Http, private router: Router) { }
  saveAdminDetails(adminDetail: AdminDetail): Observable<any>
  {
      let url = this.baseUrl + "saveAdmin";
      return this.http.post(url, adminDetail);
  }
  login(adminDetail: AdminDetail): Observable<any>
  {
      let url = this.baseUrl + "login";
      return this.http.post(url, adminDetail);
  }
  logout() 
  { 
    // Удалить токен из localStorage.
    localStorage.removeItem('token');
    this.router.navigate(['']);
  }
  /*
  * Проверить, залогинен пользователь или нет.
  */
  isLoggedIn() { 
    // создать экземпляр класса JwtHelper
    let jwtHelper = new JwtHelperService();
    // Получить токен из localStorage, так как нам нужно работать с этим токеном.
    let token = localStorage.getItem('token');
    // Проверить, есть ли у токена что-то или он null.
    if(!token)
    {
      return false;
    }
    // Получить дату истечения токена, вызывая метод getTokenExpirationDate(String) класса JwtHelper. Этот метод принимает строковое значение, которое является токеном.
    if(token)
    {
      let expirationDate = jwtHelper.getTokenExpirationDate(token);
      // Проверить, истек ли токен, вызывая метод isTokenExpired() класса JwtHelper.
      let isExpired = jwtHelper.isTokenExpired(token);
      return !isExpired;    
    }   
  }
  
  
  getAdminDetail(adminId) : Observable<any>
  {
      let url = this.baseUrl + "getAdminData/" + adminId;
       // Создать экземпляр объекта Header.
      let headers = new Headers();
      // Получить токен из localStorage.
      let token = localStorage.getItem('token');
      // Добавить заголовок Authorization.
      headers.append('Authorization', 'Bearer ' + token);
      // создать объект RequestOptions и включить его в него.
      let options = new RequestOptions({ headers: headers });
      return this.http.get(url, options);
  }
  
}

Редактировать signup.component.ts Файл

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { AdminDetail } from '../classes/admin-detail';
import { AdminService } from '../services/admin.service';
import { Router } from '@angular/router';
@Component({
  selector: 'app-signup',
  templateUrl: './signup.component.html',
  styleUrls: ['./signup.component.css'],
})}}
export class SignupComponent implements OnInit {
  private adminDetail = new AdminDetail();
  constructor(private adminService: AdminService, private router: Router) { }
  ngOnInit() {
  }
  // создать объект формы.
  form = new FormGroup({
      fullName: new FormControl('', Validators.required),
      email : new FormControl('', Validators.required),
      password: new FormControl('', Validators.required),
      confirmPassword: new FormControl('', Validators.required),
      role: new FormControl('', Validators.required),
  });
  AdminForm(AdminInformation)
  {
     let pass = this.Password.value;
     let confirmPass = this.ConfirmPassword.value;
     if(pass == confirmPass)
     {
        this.adminDetail.name = this.FullName.value;
        this.adminDetail.emailId = this.Email.value;
        this.adminDetail.password = this.Password.value;
        this.adminDetail.role = this.Role.value;
        this.adminService.saveAdminDetails(this.adminDetail).subscribe(
          response => {
              let result = response.json();
              if(result > 0)
              {
                this.router.navigate(['/login']);
              }
              else
              {
                  alert("Произошла ошибка при регистрации пользователя. Пожалуйста, попробуйте позже.")
              }
          },
          error => {
            alert("Произошла ошибка при регистрации пользователя. Пожалуйста, попробуйте позже.")
          }
        );
        
     }
     else
     {
        alert("Пароль и подтверждение пароля не совпадают.");
     }
  }
  get FullName(){
    return this.form.get('fullName');
  }
  get Email(){
      return this.form.get('email');
  }
  get Password(){
      return this.form.get('password');
  }
  get ConfirmPassword(){
      return this.form.get('confirmPassword');
  }
  get Role(){
      return this.form.get('role');
  }
}

Редактировать signup.component.html Файл

<h2>SignUp form</h2>
<form [formGroup]="form" #AdminInformation (ngSubmit)="AdminForm(AdminInformation)">
  <div class="row">
    <div class=" col-md-offset-1 col-md-4">
        <label for="fullName"> Name </label>
        <input formControlName="fullName" class="form-control" type="text"> 
    </div>
  </div>
  <div class="row">
    <div class=" col-md-offset-1 col-md-4">
        <label for="email"> Email </label>
        <input formControlName="email" class="form-control" type="text"> 
    </div>
  </div>
  <div class="row">
    <div class=" col-md-offset-1 col-md-4">
        <label for="password"> Password </label>
        <input formControlName="password" class="form-control" type="password"> 
    </div>
  </div>
  <div class="row">
    <div class=" col-md-offset-1 col-md-4">
        <label for="confirmPassword"> Confirm Password </label>
        <input formControlName="confirmPassword" class="form-control" type="password"> 
    </div>
  </div>
  <div class="row">
    <div class=" col-md-offset-1 col-md-4">
        <label for="role"> Role </label>
        <input formControlName="role" class="form-control" type="text"> 
    </div>
  </div>
  <div class="row" style="margin-top: 40px;">
    <div class="col-md-offset-1 col-md-4">
        <button class="btn btn-md btn-primary btn-style"  >Save</button>
    </div>
  </div>
</form>

Редактировать login.component.ts Файл

import { Component, OnInit } from '@angular/core';
import { FormGroup, Validators, FormControl } from '@angular/forms';
import { AdminDetail } from '../classes/admin-detail';
import { AdminService } from '../services/admin.service';
import { Router } from '@angular/router';
@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})}}
export class LoginComponent implements OnInit {
  private adminDetail = new AdminDetail();
  constructor(private adminService: AdminService, private router: Router) { }
  ngOnInit() {
    if((this.adminService.isLoggedIn()) )
    {
        this.router.navigate(['/profile', localStorage.getItem('id')]);
    }
    else
    {
        this.router.navigate(['/login']);
    }
  }
  // создать объект формы.
  form = new FormGroup({
    email : new FormControl('', Validators.required),
    password : new FormControl('', Validators.required)
  });
  Login(LoginInformation)
  {
      this.adminDetail.emailId = this.Email.value;
      this.adminDetail.password = this.Password.value;
      this.adminService.login(this.adminDetail).subscribe(
        response => {
            let result = response.json();
            
            if(result > 0)
            {
              let token = response.headers.get("Authorization");
              localStorage.setItem("token", token);
              localStorage.setItem("id", result);
  
              this.router.navigate(['/profile', result]);
            }
            if(result == -1)
            {
              alert("Пожалуйста, зарегистрируйтесь перед входом или неверное сочетание электронной почты и пароля");
            }
           
        },
        error => {
            console.log("Ошибка в аутентификации");
        }
      );
  }
  get Email(){
      return this.form.get('email');
  }
  get Password(){
      return this.form.get('password');
  }
}

Редактировать login.component.html Файл

<h2>Login form</h2>
<form [formGroup]="form" #LoginInformation (ngSubmit)="Login(LoginInformation)">
  <div class="row">
    <div class=" col-md-offset-1 col-md-4">
        <label for="email"> Email </label>
        <input formControlName="email" class="form-control" type="text"> 
    </div>
  </div>
  <div class="row">
    <div class=" col-md-offset-1 col-md-4">
        <label for="password"> Password </label>
        <input formControlName="password" class="form-control" type="password"> 
    </div>
  </div>
  <div class="row" style="margin-top: 40px;">
    <div class="col-md-offset-1 col-md-4">
        <button class="btn btn-md btn-primary btn-style"  >Login</button>
    </div>
  </div>
</form>

Редактировать profile.component.ts Файл
Пользователь, войдя в систему, будет перенаправлен на компонент конфигурации.

import { Component, OnInit } from '@angular/core';
import { AdminService } from '../services/admin.service';
import { ActivatedRoute, Router } from '@angular/router';
@Component({
  selector: 'app-profile',
  templateUrl: './profile.component.html',
  styleUrls: ['./profile.component.css']
})}}
export class ProfileComponent implements OnInit {
  private adminId;
  private haveData= 0;
  private data = [];
  private dataRequest = false;
  constructor(private adminService : AdminService, private route : ActivatedRoute, private router : Router) {  }
  ngOnInit() {
    if((this.adminService.isLoggedIn()) )
    {
      this.route.paramMap.subscribe(params => {
        this.adminId =+ params.get('adminId');
      });
    }
    else
    {
        this.router.navigate(['/login']);
    }
  }
  getAdminData()
  {
      this.haveData = 0;
      this.dataRequest = true;
      this.adminService.getAdminDetail(this.adminId).subscribe(
          response => {
              let result = response.json();
              this.data = result;
              if(result == " ")
              {
                  this.haveData = 0;
              }
              else
              {
                this.haveData = this.haveData + 1;
              }
          },
          error => {
              console.log("error while getting Admin Data");
          }
      );
  }
}

Редактировать profile.component.html Файл

<div style="text-align: right; margin-right: 40px;">
  <h2>    <a (click)= "adminService.logout()">Logout</a>    <br>    </h2>
  
</div>
<div style="text-align: center; margin-right: 40px;">
  <h2>    <a (click)="getAdminData()">Получить данные администратора</a>    <br>    </h2>
  
</div>
<div *ngIf="haveData > 0 && dataRequest">
    <table class="table table-responsive table-striped">
        <tr>
          <th>ID электронной почты</th>
          <th>Имя</th>
          <th>Пароль</th>
          <th>Роль</th>
        </tr>
        
        <ng-container *ngfor="let item of data">
            <tr>
              <td>{{item.emailId}}</td>
              <td>{{item.name}}</td>
              <td>{{item.password}}</td>
              <td>{{item.role}}</td>
            </tr>
        </ng-container>
  
      </table>
</div>
<div *ngIf="haveData == 0 && dataRequest">
    Нет данных.
</div>

Пользователь может нажатьПолучить详细信息 администраторассылку, чтобы получить详细信息 администратора.

Теперь пользователь может нажатьВыйтиВыйти из текущего состояния.