Spring Framework-9


🔐今回はログインを作成しましょう!!

login.jspの変更


login.jspのフォームを変更し、次のようにスクリプトを追加します.これは、ユーザがloginボタンを押すと、POST要求が/送信され、uservoに情報が含まれるスクリプトです.リクエストが成功した場合、返されるデータがtrueに成功した場合は/boardに移動し、そうでない場合は電子メールまたはパスワードを確認します.
<form class="user">
	<div class="form-group">
		<input type="email" class="form-control form-control-user" name="email" aria-describedby="emailHelp" placeholder="Enter Email Address...">  
        </div>
	<div class="form-group">
		<input type="password" class="form-control form-control-user" name="password" placeholder="Password">
	</div>
	<div class="form-group">
		<div class="custom-control custom-checkbox small">
			<input type="checkbox" class="custom-control-input" id="customCheck">
			<label class="custom-control-label" for="customCheck">Remember Me</label>
		</div>
	</div>
	<a id="login" class="btn btn-primary btn-user btn-block">
		Login
	</a>
	<hr>
	<a href="index.html" class="btn btn-google btn-user btn-block">
		<i class="fab fa-google fa-fw"></i> Login with Google
	</a>
	<a href="index.html" class="btn btn-facebook btn-user btn-block">
		<i class="fab fa-facebook-f fa-fw"></i> Login with Facebook
	</a>
</form>
<script>
        $("#login").click(function (){
            var userVO = new Object()
            userVO.email = $("[name='email']").val()
            userVO.password = $("[name='password']").val()

            $.ajax({
                type:'POST',
                url:'/',
                data:JSON.stringify(userVO),
                contentType:'application/json; charset=UTF-8',
                success:function (data){
                    if(data.success)
                        location.href='/board'
                    else
                        alert('email 혹은 비밀번호를 확인해주세요!')
                }
            })
        })

    </script>

UserMapperインタフェースとxmlの変更


ユーザー情報を取得するために電子メールを変更します.
<mapper namespace="ac.kr.smu.mapper.UserMapper">
    <insert id="save">
        INSERT INTO user(name,email,password)
        VALUES (#{name},#{email},#{password})
    </insert>

    <select id="checkEmailDuplication" resultType="int">
        SELECT COUNT(*) FROM user where email=#{email}
    </select>

    <select id="findByEmail" resultType="UserVO">
        SELECT * FROM user where email=#{email}
    </select>
</mapper>
public interface UserMapper {
    public void save(UserVO userVO);
    public int checkEmailDuplication(String email);
    public UserVO findByEmail(String email);
}

ユーザー・サービスの変更


パスワードが正しいことを確認した場合、trueエラーに変更してfalseを返します.
public interface UserService {
    public void save(UserVO userVO);
    public boolean checkEmailDuplication(String email);
    public boolean checkPassword(String email, String password);
}
@RequiredArgsConstructor
@Service
public class UserServiceImpl implements UserService {
    private final UserMapper userMapper;

    @Override
    public void save(UserVO userVO) {
        userMapper.save(userVO);
    }

    @Override
    public boolean checkEmailDuplication(String email) {
        return userMapper.checkEmailDuplication(email)==0;
    }

    @Override
    public boolean checkPassword(String email, String password) {
 	return password.equals(userMapper.findByEmail(email).getPassword());

    }
}

LoginControlの変更


ログイン処理のために変更します.パスワードが正しいことを確認すると、Mapのsuccessにtrue戻りが含まれ、そうでない場合false戻りが含まれます.パスワードが正しい場合は、セッションの有効期限を30分に設定し、userSessionの名前で電子メールを保存します.戻るとステータスコード200が返される.
@RestController
@RequiredArgsConstructor
@RequestMapping("/")
public class LoginController {
    private final UserService userService;

    @GetMapping
    public ModelAndView getLogin(){
        return new ModelAndView("login");
    }
    @PostMapping
    public ResponseEntity<?> postLogin(@RequestBody UserVO userVO, HttpSession session){
        Map<String,Boolean> body = new HashMap<>();
        boolean result = userService.checkPassword(userVO.getEmail(), userVO.getPassword());

        body.put("success",result);
        if(result) {
            session.setMaxInactiveInterval(60*30);//초 단위로 세션의 만료시간 설정
            session.setAttribute("userSession",userVO.getEmail());
        }

        return ResponseEntity.ok(body);

    }
}

会話とは?


ブラウザが終了する前にクライアントの要求を保持する技術.
ResponseEntityは、オブジェクトとHttpStatusなどを同時に返すクラスです.

受信者の追加


ログインが作成されました.そのため、ログインしていないユーザーにログインおよびログインコストログインページ以外のアクセス権がないことを確認する必要があります.そこで、Interceptorを使用してこの処理を行います.

LoginInterceptorの追加


LoginInterceptorクラスを追加します.このクラスはrequestからセッションを受信し、userSessionがない場合はログインページに移動して実行を続行するクラスです.
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session  = request.getSession();
        boolean chk=session.getAttribute("userSession") != null;

        if(!chk)
            response.sendRedirect("/");

        return chk;
    }
}

Interceptorとは?


要求されたクラスを切り取ります.要求がコントローラに到達する前または要求が終了した後に動作するAOP.

サーブレットコンフィグの変更


次の方法はOverrideです.ブロッキングを追加する方法.パスを使用すると、ブロッカーは、すべての受信/boardおよび/postの要求を処理できます.
@Override
public void addInterceptors(InterceptorRegistry registry) {
        WebMvcConfigurer.super.addInterceptors(registry);
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/board").addPathPatterns("/post/**");
    }

テスト


正しいログイン時





ログインしていないアクセス試行


ログが残っているかどうかを確認しましょう.LoginInterceptorの変更:
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session  = request.getSession();
        log.info(request.getRequestURI());
        log.info("userSession is null? : "+(session.getAttribute("userSession")==null));
        boolean chk=session.getAttribute("userSession") != null;

        if(!chk)
            response.sendRedirect("/");

        return chk;
    }
}

ログインしていません:

ログインなしでアクセスした場合

セッションが空であることを確認するために、ブロッキング要求がブロックされます.このリクエストはnullなので、ログインページに戻してください.