728x90

출처

토큰관리용 테이블생성

CREATE TABLE persistent_logins (
  series VARCHAR(64) NOT NULL,
  username VARCHAR(64) NOT NULL,
  token VARCHAR(64) NOT NULL,
  last_used DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY USING BTREE (series)
);

Domain 객체

package com.bx.domain;

import java.util.Date;

public class PersistentLogins {

	// pk
	private String series;
	
	private String username;
	private String token;
	private Date last_used;
	
	public PersistentLogins() {
		
	}

	public PersistentLogins(String username, String series, String token, Date last_used) {
		this.username = username;
		this.series = series;
		this.token = token;
		this.last_used = last_used;
	}

	public void setSeries(String series) {
		this.series = series;
	}

	public String getSeries() {
		return this.series;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getUsername() {
		return this.username;
	}

	public void setToken(String token) {
		this.token = token;
	}

	public String getToken() {
		return this.token;
	}

	public void setLast_used(Date last_used) {
		this.last_used = last_used;
	}

	public Date getLast_used() {
		return this.last_used;
	}

}

Mapper 인터페이스

package com.bx.persistence;

import com.bx.domain.PersistentLogins;

public interface PersistentLoginsMapper {

	public PersistentLogins selectUserToken(String cookieSeries);

	public int insertUserToken(PersistentLogins persistentLogins);

	public int updateUserToken(PersistentLogins persistentLogins);

	public int deleteOneToken(String cookieValue);

}

Mapper xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.bx.persistence.PersistentLoginsMapper">

	<!-- selectUserToken -->
	<select id="selectUserToken" parameterType="java.lang.String" resultType="com.bx.domain.PersistentLogins">
		select *
		  from persistent_logins
		 where series = #{series}
	</select>

	<!-- updateUserToken -->
	<update id="updateUserToken" parameterType="com.bx.domain.PersistentLogins" statementType="PREPARED">
		update persistent_logins
		    <trim prefix="SET" suffixOverrides=",">
		      <if test="username != null">username = #{username, jdbcType=VARCHAR} ,</if>
		      <if test="token != null">token = #{token, jdbcType=VARCHAR} ,</if>
		      <if test="last_used != null">last_used = #{last_used, jdbcType=TIMESTAMP} ,</if>
		    </trim>
		 where series = #{series}
	</update>

	<!-- insertUserToken -->
	<insert id="insertUserToken" parameterType="com.bx.domain.PersistentLogins" statementType="PREPARED">
		insert into persistent_logins(
		    <trim suffixOverrides=",">
		      <if test="series != null">series ,</if>
		      <if test="username != null">username ,</if>
		      <if test="token != null">token ,</if>
		      <if test="last_used != null">last_used ,</if>
		    </trim>
		    ) values (
		    <trim suffixOverrides=",">
		      <if test="series != null">#{series, jdbcType=VARCHAR} ,</if>
		      <if test="username != null">#{username, jdbcType=VARCHAR} ,</if>
		      <if test="token != null">#{token, jdbcType=VARCHAR} ,</if>
		      <if test="last_used != null">#{last_used, jdbcType=TIMESTAMP} ,</if>
		    </trim>
		)
	</insert>

	<!-- deleteOneToken -->
	<delete id="deleteOneToken" parameterType="java.lang.String" statementType="PREPARED">
		delete from persistent_logins
		 where series = #{cookieValue}
	</delete>

</mapper>

AbstractRememberMeServices 구현

로그인시 토큰값 DB에 저장하고, 로그아웃시 토튼값 삭제 처리

package com.oxbridge.handler;

import java.security.SecureRandom;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.codec.Base64;
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
import org.springframework.security.web.authentication.rememberme.CookieTheftException;
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationException;

import com.bx.domain.PersistentLogins;
import com.bx.persistence.PersistentLoginsMapper;

public class UserLoginRememberMeService extends AbstractRememberMeServices {
	
	private static final Logger logger = LoggerFactory.getLogger(UserLoginRememberMeService.class);
	
	/* token값 신규 생성을 위한 랜덤 넘버 생성 객체 */
	SecureRandom random;
	
	@Autowired
	private PersistentLoginsMapper mapper;

	/* 생성자 */
	public UserLoginRememberMeService(String key, UserDetailsService userDetailsService) {
		super(key, userDetailsService);
		random = new SecureRandom();
	}

	@Override
	/* 첫 로그인 시 쿠키 발행 및 토큰정보 DB 업데이트 */
	protected void onLoginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) {
		
		// 사용자 쿠키 겁색
		String cookieValue = super.extractRememberMeCookie(request);

		// 사용자 쿠키가 존재할 경우 DB에서 해당 데이터를 삭제함
		// 2차 인증하지 않으면 자동로그인 되지 못하는 쿠키가 남아있을 수 있음
		if (cookieValue != null) {
			
			// series 값 기준으로 해당 토큰을 DB에서 삭제
			mapper.deleteOneToken(decodeCookie(cookieValue)[0]);
		}

		// 새로운 series, token 값 생성
		String username = successfulAuthentication.getName();
		String newSeriesValue = generateTokenValue();
		String newTokenValue = generateTokenValue();

		// 쿠키 발급 및 DB insert
		try {
			PersistentLogins rememberMeVO = new PersistentLogins(username, newSeriesValue, newTokenValue, new Date());

			// DB insert
			mapper.insertUserToken(rememberMeVO);

			// 쿠키 발행
			String[] rawCookieValues = new String[] { newSeriesValue, newTokenValue };
			super.setCookie(rawCookieValues, getTokenValiditySeconds(), request, response);

		} catch (DataAccessException e) {
			e.printStackTrace();
		}

		/*
		// 2차 인증을 위한 메일 발송
		String ip = request.getHeader("X-Forwarded-For");
		if (ip == null) {
			ip = request.getRemoteAddr();
		}
		String userAgent = request.getHeader("user-agent");

		boolean isSended = emailSender.sendSecondCertifyingEmail(username, newSeriesValue, newTokenValue, ip, userAgent);
		if (!isSended) {
			request.getSession().setAttribute("rememberMeMsg", "메일 전송에 실패했습니다. 등록된 메일 주소를 확인해주세요.");
		}
		*/
	}

	@Override
	/* 자동 로그인 로직 - 쿠키 유효성 검증 및 사용자 정보 객체 리턴 */
	protected UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request, HttpServletResponse response) throws RememberMeAuthenticationException, UsernameNotFoundException {
		
		// 쿠키 : series, token
		// 포함된 값이 2개가 아닌 경우
		if (cookieTokens.length != 2) {
			throw new RememberMeAuthenticationException("잘못된 쿠키");
		}

		String cookieSeries = cookieTokens[0];
		String cookieToken = cookieTokens[1];

		// DB 토큰 정보 확인
		PersistentLogins rememberMeVO = mapper.selectUserToken(cookieSeries);

		// DB에 정보가 없을 경우
		if (rememberMeVO == null) {
			throw new RememberMeAuthenticationException("존재하지 않는 series");
		}

		// DB에 series는 있는데 Token 값이 같지 않을 경우
		if (!cookieToken.equals(rememberMeVO.getToken())) {

			// DB에서 해당 데이터 삭제
			mapper.deleteOneToken(cookieSeries);
			throw new CookieTheftException("변조된 쿠키 발견");
		}
		
		/*
		// DB에 series는 있는데 certified가 null인 경우 (메일 인증되지 않은 쿠키)
		if (rememberMeVO.getCertified() == null) {
			throw new RememberMeAuthenticationException("메일 인증되지 않은 쿠키");
		}
		*/

		// 유효기간 검증
		if (rememberMeVO.getLast_used().getTime() + getTokenValiditySeconds() * 1000L < System.currentTimeMillis()) {
			// DB에서 해당 데이터 삭제
			mapper.deleteOneToken(cookieSeries);
			throw new RememberMeAuthenticationException("유효기간 만료 쿠키");
		}

		// 신규 token 값으로 업데이트
		String newToken = generateTokenValue();
		rememberMeVO.setToken(newToken);
		rememberMeVO.setLast_used(new Date());

		try {
			// DB에 새로운 token 값 업데이트
			mapper.updateUserToken(rememberMeVO);

			// 변경된 token 값으로 새로운 쿠키 발행
			String[] rawCookieValues = new String[] { cookieSeries, newToken };
			super.setCookie(rawCookieValues, getTokenValiditySeconds(), request, response);

		} catch (DataAccessException e) {
			e.printStackTrace();
			throw new RememberMeAuthenticationException("새로운 token DB 업데이트 실패");
		}
		//

		// 모두 인증됐으면 사용자 정보 객체 찾아서 반환 (예외 발생 시 super에서 처리해줌)
		return getUserDetailsService().loadUserByUsername(rememberMeVO.getUsername());
	}

	@Override
	/* 로그아웃 시 쿠키/DB 정보 삭제 */
	public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
		
		logger.debug("logout-1");

		// 웹에서 모든기기 로그아웃 요청한 경우
		if (request.getParameter("logoutAllWeb") != null) {
			/*
			String username = (String) request.getParameter("logoutAllWeb");
			
			// 권한이 있을 경우에만 로그아웃 작동 (다른 사람이 URI로 직접 요청하는 경우를 막기 위함)
			if (authentication != null && authentication.getName().equals(username)) {
				mapper.deleteAllUserToken(username);
			}
			*/

			// 인증 메일에서 모든 기기 로그아웃 요청한 경우
		} else if (request.getParameter("logoutAllEmail") != null) {

			/*
			// 디코딩 후 사용자 토큰 데이터 모두 삭제
			String encodedUsername = (String) request.getParameter("logoutAllEmail");
			String[] username = emailSender.decodeValues(encodedUsername);
			if (username != null) {
				mapper.deleteAllUserToken(username[0]);
			}
			*/

			// 현재 기기 로그아웃 요청일 경우
			// series 기준으로 DB의 데이터 삭제
		} else {

			// DB token 삭제 (username이 아닌 해당 series의 정보만 삭제)
			String decodedCookieValue = super.extractRememberMeCookie(request);
			if (decodedCookieValue != null) {
				String[] cookieTokens = super.decodeCookie(decodedCookieValue);
				if (cookieTokens != null && cookieTokens.length == 2) {
					mapper.deleteOneToken(cookieTokens[0]);
				}
			}
		}

		// 쿠키 삭제
		super.logout(request, response, authentication);
	}

	/* Series, Token 랜덤값으로 생성후 인코딩 */
	private String generateTokenValue() {
		byte[] newToken = new byte[16];
		random.nextBytes(newToken);
		return new String(Base64.encode(newToken));
	}
}

Spring security 설정

	<bean id="archimAuthDetSource" class="com.bx.handler.ArchimAuthDetSource"/>
	
	<bean id="rememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
		<property name="rememberMeServices" ref="rememberMeServices"/>
		<property name="authenticationManager" ref="authenticationManager" />
	</bean>
	
	<bean id="rememberMeServices" class="com.bx.handler.UserLoginRememberMeService">
		<constructor-arg value="springRocks"/>
		<constructor-arg ref="tbUserService"/>
	</bean>
	
	<bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
		<property name="key" value="springRocks"/>
	</bean>
	
	<bean id="bxAuthenticationProvider" class="com.bx.handler.BXAuthenticationProvider"/>
	
	<security:authentication-manager alias="authenticationManager">
		<security:authentication-provider ref="bxAuthenticationProvider" /> <!-- 권한 설정할 커스텀 Bean -->
		<security:authentication-provider ref="rememberMeAuthenticationProvider" />
		<security:authentication-provider user-service-ref="tbUserService"/>
	</security:authentication-manager>

로그인 페이지

	<div class="login-content">
		<form action="<c:url value='/j_spring_security_check' />" method='POST' class="margin-bottom-0">
			<input type="hidden" id="user_type" name="user_type" value="01">
			<div class="form-group m-b-20">
				<input type="text" name='j_username' class="form-control form-control-lg inverse-mode" placeholder="아이디" required />
			</div>
			<div class="form-group m-b-20">
				<input type="password" name='j_password' class="form-control form-control-lg inverse-mode" placeholder="암호" required />
			</div>
			<div class="checkbox checkbox-css m-b-20">
				<input type="checkbox" id="remember_checkbox" name="_spring_security_remember_me"/> 
				<label for="remember_checkbox">Remember Me</label>
			</div>
			<div class="login-buttons">
				<button type="submit" class="btn btn-success btn-block btn-lg" style="font-size:large;">로그인</button>
			</div>
			<!--  csrf 공격 방어를 위해 동적 생성 -->
			<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token }" />
		</form>
	</div>
728x90
728x90

출처

pom.xml

		<dependency>
			<groupId>org.springframework.amqp</groupId>
			<artifactId>spring-amqp</artifactId>
			<version>2.1.12.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.amqp</groupId>
			<artifactId>spring-rabbit</artifactId>
			<version>2.1.12.RELEASE</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-core</artifactId>
			<version>2.12.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.12.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-annotations</artifactId>
			<version>2.12.3</version>
		</dependency>

		<!-- RabbitMQ Client -->
		<dependency>
			<groupId>com.rabbitmq</groupId>
			<artifactId>amqp-client</artifactId>
			<version>5.8.0</version>
		</dependency>

Spring AMQP 큐 메시지 송신

bluexmas-mq-rabbitmq.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:rabbit="http://www.springframework.org/schema/rabbit"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/rabbit    https://www.springframework.org/schema/rabbit/spring-rabbit.xsd
	                    http://www.springframework.org/schema/beans     https://www.springframework.org/schema/beans/spring-beans.xsd
	                    http://www.springframework.org/schema/context   http://www.springframework.org/schema/context/spring-context-2.5.xsd">

	<!-- RabbitMQ 연결 설정 -->
	<rabbit:connection-factory id="rabbitConnectionFactory" 
		virtual-host="/" 
		host="lastxmas.iptime.org" 
		port="5672"
		channel-cache-size="10" 
		username="admin" 
		password="passwd"/>
		
	<rabbit:admin connection-factory="rabbitConnectionFactory"/>
	
	<!-- Queue 등록 -->
	<rabbit:queue auto-declare="true" name="myQueue" />
	
	<rabbit:direct-exchange name="amq.direct">
		<rabbit:bindings>
			<rabbit:binding key="foo.bar" queue="myQueue"/>
		</rabbit:bindings>
	</rabbit:direct-exchange>
	
	<!-- 생산자와 소비자 모두에게 필요한 메시지 변환 -->
	<bean id="amqpMessageConverter" class="org.springframework.amqp.support.converter.Jackson2JsonMessageConverter"/>

	<!-- 메시지 리스너 설정 -->
	<rabbit:listener-container connection-factory="rabbitConnectionFactory" message-converter="amqpMessageConverter">
		<!-- 큐 myQueue 메시지는 bean id consumer의 method handleMessage가 처리한다 -->
		<rabbit:listener queues="myQueue" ref="MQConsumer" method="handleMessage"/>
	</rabbit:listener-container>
	
	<bean id="MQConsumer" class="com.bluexmas.mq.MQConsumer"/>
	
</beans>

메시지 수신 클래스 ( MQConsumer.java )

package com.bluexmas.mq;

import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.amqp.core.Message;
import org.springframework.stereotype.Component;

import com.bluexmas.dao.domain.CustomMessage;
import com.bluexmas.dao.domain.MPSMessage;

@Component
public class MQConsumer {
	
	//메시지를 처리한다.
	public void handleMessage(Message message) {
		//do Something
		System.out.println(message);		
	}
	
	//메시지를 처리한다.
	public void handleMessage(CustomMessage message) {
		//do Something
		System.out.println("--1> " +  message);
	}
	
}

Spring AMQP 큐 수동으로 전달

메시지 큐 전달 객체 ( CustomMessage.java )

package com.bluexmas.dao.domain;

public class CustomMessage {
	
	private String text;

	private int priority;

	private boolean secret;

	protected CustomMessage() {
	}

	public CustomMessage(String text, int priority, boolean secret) {
		this.text = text;
		this.priority = priority;
		this.secret = secret;
	}

	public String getText() {
		return text;
	}

	public int getPriority() {
		return priority;
	}

	public boolean isSecret() {
		return secret;
	}

	@Override
	public String toString() {
		return "CustomMessage{" + "text='" + text + '\'' + ", priority=" + priority + ", secret=" + secret + '}';
	}

}

메시지 전달 객체 ( ProducerJSon2.java )

package com.bluexmas.test;

import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;

import com.bluexmas.dao.domain.CustomMessage;
import com.fasterxml.jackson.core.JsonProcessingException;

public class ProducerJSon2 {
	public static void main(final String[] args) throws JsonProcessingException {
		// RabbitMQ 연결
		CachingConnectionFactory cf = new CachingConnectionFactory("lastxmas.iptime.org", 5672);
		cf.setUsername("admin");
		cf.setPassword("passwd");

		// 메시지 보내기
		RabbitTemplate template = new RabbitTemplate(cf);
		template.setExchange("amq.direct");
		template.setQueue("myQueue");
		template.setMessageConverter(new Jackson2JsonMessageConverter());
		
		CustomMessage customMessage = new CustomMessage("Hello Message!", 1, true);
		template.convertAndSend("foo.bar", customMessage);
		cf.destroy();
	}
}

로그

00:29:34.276 [pool-1-thread-4] DEBUG org.springframework.amqp.rabbit.listener.BlockingQueueConsumer - Storing delivery for consumerTag: 'amq.ctag-5t1nRdDJwg8A-H8jTH6DqQ' with deliveryTag: '1' in Consumer@1e292e89: tags=[[amq.ctag-5t1nRdDJwg8A-H8jTH6DqQ]], channel=Cached Rabbit Channel: AMQChannel(amqp://admin@1.229.109.140:5672/,1), conn: Proxy@eefafec Shared Rabbit Connection: SimpleConnection@3680d2bb [delegate=amqp://admin@1.229.109.140:5672/, localPort= 4263], acknowledgeMode=AUTO local queue size=0

00:29:34.293 [org.springframework.amqp.rabbit.config.ListenerContainerFactoryBean#0-1] DEBUG org.springframework.amqp.rabbit.listener.BlockingQueueConsumer - Received message: (Body:'{"text":"Hello Message!","priority":1,"secret":true}' MessageProperties [headers={__TypeId__=com.bluexmas.dao.domain.CustomMessage}, contentType=application/json, contentEncoding=UTF-8, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, redelivered=false, receivedExchange=amq.direct, receivedRoutingKey=foo.bar, deliveryTag=1, consumerTag=amq.ctag-5t1nRdDJwg8A-H8jTH6DqQ, consumerQueue=myQueue])

--1> CustomMessage{text='Hello Message!', priority=1, secret=true}
728x90
728x90

출처

사용자추가

Admin 탭으로 이동

사용자 정보를 입력하고 [Add user] 버튼 선택

가상호스트 추가

가상호스트를 추가할 사용자 선택

[Virtual Host] 선택하고 [Set permission] 버튼 선택

확인

728x90
728x90

출처

저장소 추가

X
user@localhost:~

bluesanta@bluesanta-desktop:~$ sudo apt list --installed rabbitmq-server
나열 중... 완료

RabbitMQ 설치

X
user@localhost:~

bluesanta@bluesanta-desktop:~$ sudo apt install rabbitmq-server
패키지 목록을 읽는 중입니다... 완료
의존성 트리를 만드는 중입니다       
상태 정보를 읽는 중입니다... 완료
다음의 추가 패키지가 설치될 것입니다 :
  erlang-asn1 erlang-base erlang-crypto erlang-eldap erlang-ftp erlang-inets erlang-mnesia erlang-os-mon erlang-parsetools
  erlang-public-key erlang-runtime-tools erlang-snmp erlang-ssl erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl libsctp1
  locales-all
제안하는 패키지:
  erlang erlang-manpages erlang-doc lksctp-tools
다음 새 패키지를 설치할 것입니다:
  erlang-asn1 erlang-base erlang-crypto erlang-eldap erlang-ftp erlang-inets erlang-mnesia erlang-os-mon erlang-parsetools
  erlang-public-key erlang-runtime-tools erlang-snmp erlang-ssl erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl libsctp1
  locales-all rabbitmq-server
0개 업그레이드, 20개 새로 설치, 0개 제거 및 0개 업그레이드 안 함.
38.1 M바이트 아카이브를 받아야 합니다.
이 작업 후 276 M바이트의 디스크 공간을 더 사용하게 됩니다.

RabbitMQ 실행 상태 확인

X
user@localhost:~

bluesanta@bluesanta-desktop:~$ systemctl status rabbitmq-server
● rabbitmq-server.service - RabbitMQ Messaging Server
     Loaded: loaded (/lib/systemd/system/rabbitmq-server.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2021-04-18 14:23:53 KST; 4min 59s ago
   Main PID: 2625 (beam.smp)
     Status: "Initialized"
      Tasks: 163 (limit: 18897)
     Memory: 85.5M
     CGroup: /system.slice/rabbitmq-server.service
             ├─2608 /bin/sh /usr/sbin/rabbitmq-server
             ├─2625 /usr/lib/erlang/erts-10.6.4/bin/beam.smp -W w -A 128 -MBas ageffcbf -MHas ageffcbf -MBlmbcs 512 -MHlmbcs 512 -MMmcs 30 -P 1048576 -t 5000000 -stbt db -zdbbl 128000 -K true -- -root /usr/lib/erlang -progname erl -- -home /var/lib/rabbit>
             ├─2970 erl_child_setup 65536
             ├─3007 inet_gethost 4
             └─3008 inet_gethost 4
 
 4월 18 14:23:50 bluesanta-desktop systemd[1]: Starting RabbitMQ Messaging Server...
 4월 18 14:23:53 bluesanta-desktop systemd[1]: rabbitmq-server.service: Supervising process 2625 which is not our child. We'll most likely not notice when it exits.
 4월 18 14:23:53 bluesanta-desktop systemd[1]: Started RabbitMQ Messaging Server.
 4월 18 14:23:53 bluesanta-desktop systemd[1]: rabbitmq-server.service: Supervising process 2625 which is not our child. We'll most likely not notice when it exits.

Management UI 플러그인 활성화

X
user@localhost:~

bluesanta@bluesanta-desktop:~$ sudo rabbitmq-plugins enable rabbitmq_management
Enabling plugins on node rabbit@bluesanta-desktop:
rabbitmq_management
The following plugins have been configured:
  rabbitmq_management
  rabbitmq_management_agent
  rabbitmq_web_dispatch
Applying plugin configuration to rabbit@bluesanta-desktop...
The following plugins have been enabled:
  rabbitmq_management
  rabbitmq_management_agent
  rabbitmq_web_dispatch
 
started 3 plugins.

사용자 추가

사용자 목록 조회

X
user@localhost:~

bluesanta@bluesanta-desktop:~$ sudo rabbitmqctl list_users
Listing users ...
user    tags
guest   [administrator]

사용자 추가

X
user@localhost:~

bluesanta@bluesanta-desktop:~$ sudo rabbitmqctl add_user admin 'passwd'
Adding user "admin" ...

사용자 권한 부여

X
user@localhost:~

bluesanta@bluesanta-desktop:~$ sudo rabbitmqctl set_user_tags admin administrator
Setting tags for user "admin" to [administrator] ...

암호 변경

X
user@localhost:~

bluesanta@bluesanta-desktop:~$ sudo rabbitmqctl change_password admin 'passwd'
Changing password for user "admin" ...

RabbitMQ 포트

  • 4369 : epmd, 여러 rabbitmq 서버끼리 서로를 찾을 수 있는 네임 서버 역할을 하는 데몬에서 사용
  • 5672, 5671 : AMQP 를 사용한 메시지 전달
  • 25672 : inter-node 와 CLI Tool 연결
  • 15672 : HTTP API, Management UI

RabbitMQ 관리페이지

웹브라우저로 http://serverip:15672/에 접속

MQTT 플러그인 활성화

X
user@localhost:~

bluesanta@bluesanta-desktop:~$ sudo rabbitmq-plugins enable rabbitmq_mqtt
Enabling plugins on node rabbit@bluesanta-desktop:
rabbitmq_mqtt
The following plugins have been configured:
  rabbitmq_management
  rabbitmq_management_agent
  rabbitmq_mqtt
  rabbitmq_web_dispatch
Applying plugin configuration to rabbit@bluesanta-desktop...
The following plugins have been enabled:
  rabbitmq_mqtt
 
started 1 plugins.
bluesanta@bluesanta-desktop:~$ netstat -nao | grep 1883
tcp6       0      0 :::1883                 :::*                    LISTEN      off (0.00/0/0)

728x90
728x90

출처

tomcat 설치

X
user@localhost:~

pi@Kubuntu:~$ cd /bluesanta/apps
pi@Kubuntu:/bluesanta/apps$ wget https://downloads.apache.org/tomcat/tomcat-8/v8.5.59/bin/apache-tomcat-8.5.59.tar.gz
pi@Kubuntu:/bluesanta/apps$ tar xvfz apache-tomcat-8.5.59.tar.gz

tomcat /opt 디렉토리에 소프트 링크 걸기

X
user@localhost:~

pi@Kubuntu:/bluesanta/apps$ sudo ln -s /bluesanta/apps/apache-tomcat-8.5.59 /opt/apache-tomcat-8.5.59

서비스 등록 파일 tomcat.service 생성

X
user@localhost:~

pi@Kubuntu:/bluesanta/apps$ cd /etc/systemd/system
pi@Kubuntu:/etc/systemd/system$ sudo vi /etc/systemd/system/tomcat.service

tomcat.service 내용

[Unit]
Description=tomcat 8
After=network.target syslog.target

[Service]
Type=forking
Environment="JAVA_HOME=/opt/jdk1.8.0_271"
User=root
Group=root
ExecStart=/opt/apache-tomcat-8.5.59/bin/startup.sh
ExecStop=/opt/apache-tomcat-8.5.59/bin/shutdown.sh

[Install]
WantedBy=multi-user.target

tomcat 서비스 등록

X
user@localhost:~

pi@Kubuntu:/etc/systemd/system$ sudo systemctl enable tomcat.service
Created symlink /etc/systemd/system/multi-user.target.wants/tomcat.service → /etc/systemd/system/tomcat.service.

tomcat 서비스 실행

X
user@localhost:~

pi@Kubuntu:/etc/systemd/system$ sudo systemctl start tomcat.service

tomcat 서비스 상태 확인

X
user@localhost:~

pi@Kubuntu:/etc/systemd/system$ sudo systemctl status tomcat.service
● tomcat.service - tomcat 8
     Loaded: loaded (/etc/systemd/system/tomcat.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2020-11-14 14:27:13 KST; 39s ago
    Process: 103228 ExecStart=/opt/apache-tomcat-8.5.59/bin/startup.sh (code=exited, status=0/SUCCESS)
   Main PID: 103256 (java)
      Tasks: 33 (limit: 18694)
     Memory: 119.5M
     CGroup: /system.slice/tomcat.service
             └─103256 /usr/bin/java -Djava.util.logging.config.file=/opt/apache-tomcat-8.5.59/conf/logging.properties -Djava.util.logging.manager=org.ap>
11월 14 14:27:13 Kubuntu systemd[1]: Starting tomcat 8...
11월 14 14:27:13 Kubuntu startup.sh[103228]: Tomcat started.
11월 14 14:27:13 Kubuntu systemd[1]: Started tomcat 8.

728x90
728x90

출처

Subversion 플로그인 설치

Deploy to container 플로그인 설치

프로젝트 생성

[새로운 Item] 메뉴 선택

item name(프로젝트 이름) 설정, Freestyle project, [OK] 버튼 선택

Subversion 선택, URL 주소 설정, Svn 접속 계정 추가 

Svn 계정 설정, [Add] 버튼 선택

추가 Svn 주소가 있는 경우, [Add module] 버튼 선택

Subversion 선택, URL 주소 설정

Build에서 [Invoke Ant] 설정

Ant - Target과 빌드 파일 설정

빌드 후 조치(배포), [Deploy war/ear to a container] 선택

베포 웹서버 설정 

728x90
728x90

출처

%TOMCAT_HOME%/conf/tomcat-users.xml

관리자 페이지는 manager-gui 권한의 활성화와 계정 정보가 설정되어야 사용이 가능하므로 %TOMCAT_HOME%/conf/tomcat-users.xml 파일을 열어서 아래와 같이 manager-gui 권한을 추가합니다.

<!--
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
  <user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
  <user username="role1" password="<must-be-changed>" roles="role1"/>
-->
	
	<!-- manager-gui 권한 추가 -->
	<role rolename="manager-gui"/>
	<role rolename="manager-script"/>
	<role rolename="manager-status"/>
	<user username="admin" password="admin" roles="manager-gui,manager-script,manager-status"/>
</tomcat-users>

관리자 페이지 접속

관리자 암호를 설정하고 [로그인] 버튼 선택

관리자 페이지

728x90
728x90

출처

Jenkins war 다운로드

Jenkins 사이트의 war 파일 다운로드

Jenkins war 복사

%TOMCAT_HOME%/warapps 폴더에 jenkins.war 파일 복사

Jenkins 접속

웹브라우져에서 http://localhost:8080/jenkins 접속

Unlock Jenkins

아래 경로에 비밀번호가 적힌 파일(initialAdminPassword)에 적힌 비밀번호를 확인 후 비밀번호를 입력하고, [Continue] 버튼 선택

플로그인 설치

[Install suggested plugins] 선택하고 설치 - 나중에 플러그인을 추가, 삭제 가능

플러그인 설치 과정

사용자 추가

Jenkins URL 정의

Jenkins 실행

Jenkins 설치 관료후 메인 화면

728x90

+ Recent posts