Статьи

Создайте новое веб-приложение с нуля, используя Spring boot, Thymeleaf, AngularJS — часть 3

В предыдущих блогах мы создавали целевую страницу с использованием Thymeleaf, Bower и Bootstrap и разворачивали ее в Heroku.
В этом блоге мы представим некоторые функциональные возможности AngularJS для внешнего интерфейса и Spring Boot Webservices для внутреннего интерфейса.

Мы начнем с раздела Вход / Выход. Начнем с установки AngularJS в нашем приложении с использованием Bower.

Представляем AngularJS

1
$ bower install angular --save

Это добавит угловые зависимости внутри папки bower_components. Для того, чтобы угловой вводился в нашу HTML-страницу, нам нужно сделать 2 вещи
1) Добавьте путь angular.min.js в наш HTML-файл

1
<script src="./bower_components/angular/angular.min.js" type="text/javascript"></script>

2. Пометьте тело как ng-app = «myModule», что означает, что нам нужно определить модуль JavaScript, который Angular будет распознавать как приложение под названием «myModule». Угловой модуль похож на контейнер для различных частей вашего приложения — контроллеров, сервисов, фильтров, директив и т. Д.

1
<body ng-app="myModule">

Теперь нам нужно определить этот модуль «myModule» в файле JS, мы можем назвать этот файл как app.js с компонентами:

1
2
3
4
5
6
7
angular.module('myModule', [])
  .controller('home', function($http) {
  var self = this;
  $http.get('/resource/').then(function(response) {
    self.message = response.data;
  })
});

Здесь мы видим, что мы определяем контроллер с именем «home» в «myModule», этот контроллер будет использоваться для передачи значений в HTML через привязку данных, модель здесь — «message».

Данные будут извлечены через HTTP GET, сделав вызов REST нашей подпружиненной стороне.
Итак, давайте посмотрим, как создать Spring Rest Controller:

Контроллер Spring Rest

Мы уже добавили зависимость "spring-boot-starter-web" поэтому нам не нужно больше зависимости от весенней загрузки для построения наших Rest Controllers.

Мы создадим LoginController

01
02
03
04
05
06
07
08
09
10
@RestController
public class LoginController {
 
    @RequestMapping("/resource")
    public Map<String,Object> home() {
        Map<String,Object> model = new HashMap<String,Object>();
        model.put("id", UUID.randomUUID().toString());
        model.put("content", "Hello World");
        return model;
    }

Теперь, если вы поместите этот кусок кода в ваш index.html в отдельный div, вы увидите, что этот div теперь динамически загружает данные из серверной части.

Чтобы увидеть данные в HTML, нам нужно сделать это:

1
2
3
4
<div ng-controller="home as home">
  <p>The ID is {{home.message.id}}</p>
  <p>The content is {{home.message.content}}</p>
</div>

До этого момента мы просто могли использовать angularJS на нашей статической странице, получать некоторую информацию из бэкэнд-контроллера Rest и отображать ее с помощью AngularJS.

Здание Вход / Выход

Теперь, когда у нас есть модуль angularJS на нашей странице индекса, давайте реализуем функцию входа / выхода из системы с помощью Spring Security.

Для создания функции входа / выхода нам нужно сделать 3 HTML-страницы.
1) index.html — это будет целевая страница, где мы добавим навигацию для входа и выхода из системы. (это у нас уже есть)
2) home.html — это будет страница, на которую будет перенаправляться после входа пользователя в систему.
3) login.html — это будет страница с полем имени пользователя и пароля для ввода учетных данных для входа.

Для маршрутизации между этими страницами мы будем использовать ng-route . Модуль ngRoute предоставляет службы маршрутизации и глубоких ссылок и директивы для угловых приложений. Чтобы установить ngRoute с помощью bower, мы выполним следующую команду:

1
bower install [email protected]

Затем включите это в ваш index.html:

1
2
<script src="path/to/angular.js"></script>
<script src="path/to/angular-route.js"></script>

Шаг 1. Добавьте навигацию в index.html.

Чтобы добавить навигацию, нам нужно добавить этот блок кода в тело.

1
2
3
4
5
6
7
8
<div ng-controller="navigation as nav" class="container">
        <ul class="nav nav-pills" role="tablist">
            <li class="active"><a href="#/">home</a></li>
            <li><a href="#/login">login</a></li>
            <li ng-show="authenticated"><a href="" ng-click="nav.logout()">logout</a></li>
        </ul>
    </div>
    <div ng-view class="container"></div>

В разделе «ng-view» будет отображена неполная страница «login.html».

Измените файл app.js, чтобы определить маршруты:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
angular.module('myModule', [ 'ngRoute' ])
  .config(function($routeProvider, $httpProvider) {
 
    $routeProvider.when('/', {
      templateUrl : 'home.html',
      controller : 'home',
      controllerAs: 'controller'
    }).when('/login', {
      templateUrl : 'login.html',
      controller : 'navigation',
      controllerAs: 'controller'
    }).otherwise('/');
 
  })
  .controller('home', function($http) {
    var self = this;
    $http.get('/resource/').then(function(response) {
      self.message = response.data;
    })
  })
  .controller('navigation',
  function($rootScope, $http, $location) {
  var self = this
 
 var authenticate = function(credentials, callback){
 
    var headers = credentials ? {authentication : "Basic "
      + btoa(credentials.username + ":"+credentials.password)
      } : {};
 
      $http.get('user', {headers : headers}).then(function(response) {
            if (response.data.name) {
              $rootScope.authenticated = true;
            } else {
              $rootScope.authenticated = false;
            }
            callback && callback();
          }, function() {
            $rootScope.authenticated = false;
            callback && callback();
          });
 }
 
 authenticate();
 
  self.credentials = {};
  self.login = function() {
      authenticate(self.credentials, function() {
        if ($rootScope.authenticated) {
          $location.path("/");
          self.error = false;
        } else {
          $location.path("/login");
          self.error = true;
        }
      });
  };
 
self.logout = function() {
        $http.post('logout', {}).finally(function() {
        $rootScope.authenticated = false;
        $location.path("/");
        });
    }
  });

Здесь мы определили 2 контроллера и 1 конфигурацию и несколько функций, которые будут использоваться контроллерами. «Config» используется для определения путей и маршрутизации с использованием ng-route. Контроллер «навигация» используется для вызова функций входа, выхода из системы и аутентификации в соответствии с определением Контроллер «home» используется для отправки приветствия на домашней странице.

authenticated переменная определяется для предоставления доступа аутентифицированному пользователю на страницах.

Шаг 2: Добавьте частичную страницу login.html

Здесь мы создадим частичную страницу login.html, которая будет отображаться внутри div, который помечен как ng-view.

Login.html

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<div class="alert alert-danger" ng-show="controller.error">
    There was a problem logging in. Please try again.
</div>
<form role="form" ng-submit="controller.login()">
    <div class="form-group">
        <label for="username">Username:</label> <input type="text"
            class="form-control" id="username" name="username" ng-model="controller.credentials.username"/>
    </div>
    <div class="form-group">
        <label for="password">Password:</label> <input type="password"
            class="form-control" id="password" name="password" ng-model="controller.credentials.password"/>
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
</form>

Затем нам нужны RestControllers для аутентификации с использованием Spring Security. Мы будем использовать аутентификацию по умолчанию для пользователя Spring Security. Мы сделаем UserController следующим методом:

1
2
3
4
@RequestMapping("/user")
    public Principal user(Principal user) {
        return user;
    }

Для работы Spring Security нам нужно добавить это в Application.java

01
02
03
04
05
06
07
08
09
10
11
12
13
@Configuration
  @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
  protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
      http
        .httpBasic()
      .and()
        .authorizeRequests()
          .antMatchers("/index.html", "/home.html", "/login.html", "/").permitAll()
          .anyRequest().authenticated();
    }
  }

Шаг 3: Добавьте страницу home.html с приветственным сообщением.

1
2
3
4
5
6
7
8
<h1>Message</h1>
<div ng-show="authenticated">
    <p>The ID is {{controller.message.id}}</p>
    <p>The content is {{controller.message.content}}</p>
</div>
<div  ng-show="!authenticated">
    <p>Login to see your message</p>
</div>

Переменная «authenticated» используется для предоставления доступа к страницам.

До сих пор мы успешно использовали Angular JS для входа и выхода с помощью Spring Security. Но в реальном приложении нам нужно, чтобы реальные пользователи проходили аутентификацию в базе данных пользователей. В следующем блоге мы собираемся создать приложение с аутентификацией пользователей из пользовательской БД.

PS: примеры были приведены из весеннего блога: https://spring.io/guides/tutorials/spring-security-and-angular-js/