[Spring] 게시판 만들기 11 – 계정 생성하기 (Spring Security 3)

권한, 게시판(카테고리)를 만들기 이전에 해당 기능들을 이용할 수 있는 계정부터 만들 수 있게 페이지를 생성한다.

1. WEB-INF/jsp/admin 아래 페이지 생성

우선 계정관리 페이지를 하나 만든다

user_management.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title>사용자 관리화면</title>

    <sec:csrfMetaTags />

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

    <link rel="stylesheet" href="/css/main.css">

</head>

<body>

    <header>

        <nav>

            <div class="menu">

                <div class="menu-item"><a href="${pageContext.request.contextPath}/">홈화면으로</a></div>

                <div class="menu-item"><a href="${pageContext.request.contextPath}/admin/userList">사용자관리화면</a></div>

                <div class="menu-item"><a href="${pageContext.request.contextPath}/admin/roleList">권한관리화면</a></div>

                <div class="menu-item"><a href="${pageContext.request.contextPath}/admin/boardList">게시판화면</a></div>

            </div>

        </nav>

    </header>

    <main>

        <nav>

            <ul>

                <li><a href="${pageContext.request.contextPath}/admin/userList" id="userList">사용자 목록</a></li>

                <li><a href="${pageContext.request.contextPath}/admin/addUserForm" id="addUser">사용자 등록</a></li>

            </ul>

        </nav>

        <section id="content">

            <h2>사용자 목록</h2>

            <form action="/deleteUser" method="post">

                <sec:csrfInput />

                <!-- 사용자 목록을 테이블로 표시합니다. -->

                <table border="1">

                    <thead>

                        <tr>

                            <th>사용자 ID</th>

                            <th>이름</th>

                            <th>관리</th>

                        </tr>

                    </thead>

                    <tbody>

                        <c:forEach var="user" items="${users}">

                            <tr>

                                <td>${user.username}</td>

                                <td>${user.name}</td>

                                <td><a href="/admin/modifyUserForm?username=${user.username}">수정</a></td>

                            </tr>

                        </c:forEach>

                    </tbody>

                </table>

            </form>

        </section>

    </main>

    <script>

    </script>

</body>

</html>

레이아웃을 좀 바꾸었는데, 우선 상단에 홈화면/사용자/권한/게시판 관리화면을 놓고

main 에 섹션을 나누어 왼쪽측면은 메뉴, 가운데는 내용을 표시하도록 바꿨다.

그리고 앞으로 만들 사용자목록, 등록 /권한/게시판 관련 a href 링크도 추가해두었음.

사용자 등록및 목록 페이지도 만들어둔다.

사용자등록화면

user_add_form.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title>사용자 등록화면</title>

    <sec:csrfMetaTags />

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

    <link rel="stylesheet" href="/css/main.css">

</head>

<body>

    <header>

        <nav>

            <div class="menu">

                <div class="menu-item"><a href="${pageContext.request.contextPath}/">홈화면으로</a></div>

                <div class="menu-item"><a href="${pageContext.request.contextPath}/admin/userList">사용자관리화면</a></div>

                <div class="menu-item"><a href="${pageContext.request.contextPath}/admin/roleList">권한관리화면</a></div>

                <div class="menu-item"><a href="${pageContext.request.contextPath}/admin/boardList">게시판화면</a></div>

            </div>

        </nav>

    </header>

    <main>

        <nav>

            <ul>

                <li><a href="${pageContext.request.contextPath}/admin/userList" id="userList">사용자 목록</a></li>

                <li><a href="${pageContext.request.contextPath}/admin/addUserForm" id="addUser">사용자 등록</a></li>

            </ul>

        </nav>

        <section id="content">

        <form action="/admin/addUser" method="post">

            <sec:csrfInput />

    <div>

        <label for="username">ID:</label>

        <input type="text" id="username" name="username" required>

    </div>

    <div>

        <label for="password">Password:</label>

        <input type="password" id="password" name="password" required>

    </div>

    <div>

        <label for="name">이름:</label>

        <input type="text" id="name" name="name" required>

    </div>

    <div>

        <button type="submit">등록</button>

    </div>

</form>

</section>

</main>

<script>

</script>

</body>

</html>

form 태그로 제출하여 등록하는 일반적인 페이지

사용자 수정화면

user_modify_form.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title>사용자 관리화면</title>

    <sec:csrfMetaTags />

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

    <link rel="stylesheet" href="/css/main.css">

</head>

<body>

    <header>

        <nav>

            <div class="menu">

                <div class="menu-item"><a href="${pageContext.request.contextPath}/">홈화면으로</a></div>

                <div class="menu-item"><a href="${pageContext.request.contextPath}/admin/userList">사용자관리화면</a></div>

                <div class="menu-item"><a href="${pageContext.request.contextPath}/admin/roleList">권한관리화면</a></div>

                <div class="menu-item"><a href="${pageContext.request.contextPath}/admin/boardList">게시판화면</a></div>

            </div>

        </nav>

    </header>

    <main>

        <nav>

            <ul>

                <li><a href="${pageContext.request.contextPath}/admin/userList" id="userList">사용자 목록</a></li>

                <li><a href="${pageContext.request.contextPath}/admin/addUserForm" id="addUser">사용자 등록</a></li>

            </ul>

        </nav>

        <section id="content">

            <form action="/admin/modifyUser" method="post">

            <sec:csrfInput />

    <div>

        <label for="username">ID:</label>

        <input type="text" id="username" name="username" value="${user.username}" readonly>

    </div>

    <div>

        <label for="password">Password:</label>

        <input type="password" id="password" name="password" value="${user.password}" required>

    </div>

    <div>

        <label for="name">이름:</label>

        <input type="text" id="name" name="name" value="${user.name}" required>

    </div>

    <div>

        <button type="submit">수정</button>

    </div>

</form>

<button id="deleteUser" value="${user.username}">사용자 삭제</button>

        </section>

    </main>

    <script>

     $.ajaxSetup({

            headers: {

                'X-CSRF-TOKEN': '${_csrf.token}'

            }

        });

        $('#deleteUser').click(function(){

            let username = $(this).val();

            if(confirm('삭제 하시겠습니까?')){

                $.ajax({

                    url: '/admin/deleteUser',

                    method: 'POST',

                    data: { username, username },

                    success: function(data){

                        console.log(data);

                        window.location.href = '/admin/userList'

                    }, error: function(err){

                        console.log(err);

                    }

                });

            } else {

                console.log("취소");

            }

        });

    </script>

</body>

</html>

삭제를 한번 막기위해 confirm 함수를 사용하였음.

현재 spring security 를 보면 csrf 를 disable 해두었는데, 앞으로는 이 기능도 풀예정이니 정상적인 post 방식을 사용하기 위해 아래와같은 코드를 집어넣은것을 볼 수 있다.

<sec:csrfInput />

     $.ajaxSetup({

            headers: {

                'X-CSRF-TOKEN': '${_csrf.token}'

            }

        });

하나만 있어도 잘 됨.

SecurityConfig.java 에서

        // http  

        //         .csrf((auth) -> auth.disable());

위 코드를 이제 주석처리해주자. 앞으로 form 태그 및 POST는 위 토큰을 넣어 정상 처리가 가능하게끔 한다.

(이전의 모든 form 태그들에 위 코드를 추가해야함.)

2. 컨트롤러 추가

admin  관련업무라서 adminController 를 추가하였다.

@Controller

@PreAuthorize("hasRole('ROLE_ADMIN')")

@RequestMapping("/admin")

public class adminController {

    @Autowired

    UserService userService;

    @Autowired

    PostService postService;

    @Autowired

    SecurityUtil securityUtil;

    ModelAndView mav = new ModelAndView();

또한 앞으로 만들 UserService  와 기존의 PostService (카테고리 추가용), 

Spring security 를 이용할 securityUtil 을 미리 Autowired 시켜두었다.

GetMapping 을 통해 페이지로 이동 시킬 수 있게 해준다. (위 a href 로 적용해둠)

@GetMapping("/userList")

    public ModelAndView userListPage() {

        mav.addObject("users", userService.findAllUser());

        mav.setViewName("admin/user_management");

        return mav;

    }

    @GetMapping("/addUserForm")

    public String addUserForm() {

        return "admin/user_add_form";

    }

    @GetMapping("/modifyUserForm")

    public ModelAndView modifyUserForm(HttpServletRequest request) {

        String username = request.getParameter("username");

        mav.addObject("user", userService.getUserInfo(username));

        mav.setViewName("admin/user_modify_form");

        return mav;

    }

 PostMapping 으로 로직을 구현해서 처리한다.

@PostMapping("/addUser")

    public String registerUser(@ModelAttribute User user) {

        userService.addUser(user);

        return "redirect:/admin/userList";

    }

(userService 는 이후 한번에 기록 예정)

유저 등록

@PostMapping("/modifyUser")

    public String modifyUser(@ModelAttribute User user){

        userService.modifyUserInfo(user);

        return "redirect:/admin/userList";

    }

    @PostMapping("/deleteUser")

    public ResponseEntity<String> deleteUser(HttpServletRequest request){

        String username = request.getParameter("username");

        userService.deleteUser(username);

        return ResponseEntity.ok("");

    }

3. 서비스 추가

@Service

public class UserService {

    @Autowired

    UserDao userDao;

    @Autowired

    PasswordEncoder passwordEncoder;

    public void addUser(User user) {

        String encodedPassword = passwordEncoder.encode(user.getPassword());

        user.setPassword(encodedPassword);

        userDao.insertUser(user);

    }

유저등록시 PAsswordEncoder 를 통해  비밀번호 암호화를 한다. (SpringSecurity)

public List<User> findAllUser() {

        return userDao.selectAllUser();

    }

    public User getUserInfo(String username) {

        return userDao.selectUserInfo(username);

    }

    public void modifyUserInfo(User user) {

        String password = user.getPassword();

        user.setPassword(passwordEncoder.encode(password));

        userDao.modifyUserInfo(user);

    }

    @Transactional

    public void deleteUser(String username) {

        userDao.deleteRoleUserByUsername(username);

        userDao.deleteUser(username);

    }

4. Dao 만들기

public void insertUser(User user) {

        sqlSession.insert("UserMapper.insertUser", user);

    }

    public List<User> selectAllUser() {

        return sqlSession.selectList("UserMapper.selectAllUser");

    }

    public List<User> selectUserByRoleId(String roleId) {

        return sqlSession.selectList("UserMapper.selectUserByRoleId", Integer.parseInt(roleId));

    }

    public User selectUserInfo(String username) {

        return sqlSession.selectOne("UserMapper.selectUserInfo", username);

    }

    public void deleteUser(String username) {

        sqlSession.delete("UserMapper.deleteUser", username);

    }

    public void modifyUserInfo(User user) {

        sqlSession.update("UserMapper.modifyUserInfo", user);

    }

5. XML SQL Query작성

mapper-user.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="UserMapper">

<select id="selectByUsername" parameterType="String" resultType="com.example.post.model.User">

  SELECT * FROM USER1 WHERE username = #{username}

</select>

<insert id="insertUser" parameterType="com.example.post.model.User">

  INSERT INTO USER1 (username, password, name) values (#{username}, #{password}, #{name})

</insert>

<select id="selectAllUser" resultType="com.example.post.model.User">

  SELECT * FROM USER1;

</select>

<insert id="insertRoleByUsername" parameterType="map">

  INSERT INTO role_user1 (username, roleId) VALUES (#{username}, #{roleId})

</insert>

<select id="selectUserByRoleId" parameterType="int" resultType="com.example.post.model.User">

select u.username, u.name, c.roleId from user1 u

left join ( select * from role_user1 where roleId = #{roleId} ) c on u.username = c.username;

</select>

<select id="selectUserInfo" parameterType="String" resultType="com.example.post.model.User">

  SELECT * FROM user1 WHERE username = #{username}

</select>

<update id="modifyUserInfo" parameterType="com.example.post.model.User">

  UPdate USER1 SET password = #{password}, name = #{name} WHERE username = #{username}

</update>

<delete id="deleteUser" parameterType="String">

  DELETE FROM user1 WHERE username = #{username}

</delete>

</mapper>

작성해준다.

이러면 우선 User 등록은 끝

Leave a Comment