システムからユーザーをログアウトするために次のコードを使用しています。
/**
* This function helps to set the session attribute for the present user to null and then
* removes the attribute itself and this helps in clearing the session
* @param request
* @param response
*/
@RequestMapping(value = AuthConstants.EXIT, method = RequestMethod.POST)
public void exitPrime(HttpServletRequest request, HttpServletResponse response) {
/*Getting session and then invalidating it*/
HttpSession session = request.getSession(false);
if(request.isRequestedSessionIdValid() && session != null)
{
session.invalidate();
}
}
これにより、ログアウトは成功しますが、ログイン中に指定されたJSESSION IDはブラウザに残ります。これは、新しいユーザーに対してログイン中に同じJSESSION IDが再び使用されるためです。 JSESSIONID Cookieを現在のセッションでのみ有効にし、ユーザーがログアウトすると、次回のログインでは破棄または無効にする必要があります。私のログインコードは次のとおりです:-
/**
* This method allows one to log into the system and generates a token for a valid employee.
* @param authRequest
* @param request
* @param response
* @return
*/
@RequestMapping(value = AuthConstants.ENTRY, method = RequestMethod.POST, consumes = ApplicationConstants.APPLICATION_JSON)
public @ResponseBody
AuthResponse primeEntry(@RequestBody AuthRequest authRequest,HttpServletRequest request, HttpServletResponse response) {
AuthResponse authResponse = new AuthResponse();
if(authRequest != null && authRequest.getEmployeeAuth().getEmployeeNumber() != null
&& !authRequest.getEmployeeAuth().getEmployeeNumber().isEmpty()){
/*To check whether the user is valid*/
String employeeNumber = authRequest.getEmployeeAuth().getEmployeeNumber();
UserBean userBean = new UserBean();
userBean = userService.getUser(employeeNumber);
if(userBean != null)
{
HttpSession session = request.getSession(true);
session.setAttribute("user", userBean);
setAuthResponseSuccess(authResponse);
}else{
/*If user does not exist the too throw error 500*/
setAuthResponseFailure(authResponse);
}
}else{
/*If input JSON is not valid then throw error 500*/
setAuthResponseFailure(authResponse);
}
return authResponse;
}
Spring 3.2を使用していますが、手動でログインとログアウトを行いたいです。助けてください。
フルクラスコード
@Controller
@RequestMapping(value = "/auth")
public class AuthController {
@Autowired
HttpServletRequest request;
@Autowired
HttpSession session;
@Autowired
IUserService userService;
/**
* This method allows one to log into the system and generates a token for a valid employee.
* @param authRequest
* @param request
* @param response
* @return
*/
@RequestMapping(value = AuthConstants.ENTRY, method = RequestMethod.POST, consumes = ApplicationConstants.APPLICATION_JSON)
public @ResponseBody
AuthResponse primeEntry(@RequestBody AuthRequest authRequest,HttpServletRequest request, HttpServletResponse response) {
AuthResponse authResponse = new AuthResponse();
if(authRequest != null && authRequest.getEmployeeAuth().getEmployeeNumber() != null
&& !authRequest.getEmployeeAuth().getEmployeeNumber().isEmpty()){
/*To check whether the user is valid*/
String employeeNumber = authRequest.getEmployeeAuth().getEmployeeNumber();
UserBean userBean = new UserBean();
userBean = userService.getUser(employeeNumber);
if(userBean != null)
{
HttpSession session = request.getSession(true);
session.setAttribute("user", userBean);
setAuthResponseSuccess(authResponse);
}else{
/*If user does not exist the too throw error 500*/
setAuthResponseFailure(authResponse);
}
}else{
/*If input JSON is not valid then throw error 500*/
setAuthResponseFailure(authResponse);
}
return authResponse;
}
/**
* This function helps to set the session attribute for the present user to null and then
* removes the attribute itself and this helps in clearing the session
* @param request
* @param response
*/
@RequestMapping(value = AuthConstants.EXIT, method = RequestMethod.POST)
public void exitPrime(HttpServletRequest request, HttpServletResponse response) {
/*Getting session and then invalidating it*/
HttpSession session = request.getSession(false);
if(request.isRequestedSessionIdValid() && session != null)
{
session.invalidate();
}
}
private AuthResponse setAuthResponseFailure(AuthResponse authResponse) {
authResponse.setResponseCode(ApplicationConstants.INTERNAL_ERROR_CODE);
authResponse.setStatus(StatusType.FAILURE);
authResponse.setResponseMsg(ApplicationConstants.INTERNAL_ERROR_MESSAGE);
return authResponse;
}
private AuthResponse setAuthResponseSuccess(AuthResponse authResponse){
authResponse.setResponseCode(ApplicationConstants.OK);
authResponse.setStatus(StatusType.SUCCESS);
authResponse.setResponseMsg(ApplicationConstants.LOGIN_SUCCESS);
return authResponse;
}
}
少し実験した結果、ブラウザーのCookieの値を保持したい場合は何もしないでください。上記のコードは問題なく機能するという結論に達しました。一方、次のようなCookieの出力が必要な場合
Set-Cookie: JSESSIONID=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/
次に、このコードスニペットを使用して試してみます。
private void handleLogOutResponseCookie(HttpServletResponse response) {
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
cookie.setMaxAge(0);
cookie.setValue(null);
cookie.setPath("/");
response.addCookie(cookie);
}
これにより、問題が解決し、ログアウト中にCookieが破壊されます。
ブラウザに残っているJSESSIONIDがすでに無効である限り、何も問題はありません。 JSESSIONIDは、実際のデータを含まないランダムな文字の集まりです。
ただし、クラスレベルで_@SessionAttributes
_アノテーションを使用し、session.invalidate()
を試行したことが問題であると思われます。前のセッションが無効になった後のこのシナリオでは、指定されたモデル属性をセッションに永続化する必要があるため、Springは自動的に新しいセッション(およびJSESSIONID)を作成しますになります。
IMOのより良いアプローチは、_@SessionAttributes
_を持たない新しいコントローラーを作成し、そこからセッションを無効にすることです。
まだ実際かどうかはわかりませんが、LogoutFilterをこのように拡張して、カスタムCookieの無効化など、ログアウト時に実行する正確な手順を指定できます。
<beans:bean id="sessionInvalidationFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<beans:property name="filterProcessesUrl" value="/logout"/>
<beans:constructor-arg>
<beans:array>
<beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
<beans:bean class="org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler">
<beans:constructor-arg value="JSESSIONID"/>
</beans:bean>
</beans:array>
</beans:constructor-arg>
</beans:bean>
考えられる1つの方法は、ログアウトアクションでJSESSIONID
Cookieを削除することです。 Cookieを削除する方法は、次のようにその有効期間をゼロに設定することです。
_Cookie cookie = new Cookie();
cookie.setValue(null);
cookie.setMaxAge(0);
cookie.setPath("/");
_
ここで、ルートとしてパスを追加しました。正しいパスについては、ブラウザのJSESSIONID
Cookieを確認してください。
これを入手したら、これを応答に追加します
_response.addCookie(cookie);
_
このコードをexitPrime()
メソッドに配置できます。
以前にリストされたアプローチは私にはうまくいきませんでしたが、いくつかの変更を加えて動作させましたが、YMMVでのテストは限られていました。
protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
HttpSession session = req.getSession(false);
if (session != null) {
String sessionId = session.getId();
session.invalidate();
Cookie[] cookies = req.getCookies();
for (Cookie cookie : cookies) {
if (sessionId.equalsIgnoreCase(cookie.getValue())) {
cookie.setMaxAge(0);
cookie.setValue(null);
cookie.setDomain(req.getServerName());
cookie.setPath(req.getServletContext().getContextPath() + "/");
cookie.setSecure(req.isSecure());
res.addCookie(cookie);
break;
}
}
}
}
Tomcatは、コンテキストパスの最後にスラッシュを追加します。さて、delete-cookie属性を設定すると、Springは最後にスラッシュなしでパスのcookieを見つけようとします。 Cookieが見つからないため、Cookieは削除されず、ログインページではなくセッション有効期限ページが表示されます。
次の回避策がトリックを行います。
public void logout(HttpServletRequest request, HttpServletResponse response,
Authentication auth) {
Cookie cookieWithSlash = new Cookie("JSESSIONID", null);
//Tomcat adds extra slash at the end of context path (e.g. "/foo/")
cookieWithSlash.setPath(request.getContextPath() + "/");
cookieWithSlash.setMaxAge(0);
Cookie cookieWithoutSlash = new Cookie("JSESSIONID", null);
//JBoss doesn't add extra slash at the end of context path (e.g. "/foo")
cookieWithoutSlash.setPath(request.getContextPath());
cookieWithoutSlash.setMaxAge(0);
//Remove cookies on logout so that invalidSessionURL (session timeout) is not displayed on proper logout event
response.addCookie(cookieWithSlash); //For Tomcat
response.addCookie(cookieWithoutSlash); //For JBoss
}