-
Notifications
You must be signed in to change notification settings - Fork 4
Enhance Remember Me Feature for Login #103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -165,21 +165,29 @@ | |||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
@RequestMapping(value = "/login", method = RequestMethod.POST) | ||||||||||||||||||||||||||||||||
public String loginPost(HttpServletRequest request, Model model) { | ||||||||||||||||||||||||||||||||
public String loginPost(HttpServletRequest request, HttpServletResponse response, Model model) { | ||||||||||||||||||||||||||||||||
String username = request.getParameter("username"); | ||||||||||||||||||||||||||||||||
String password = request.getParameter("password"); | ||||||||||||||||||||||||||||||||
boolean rememberMe = "on".equals(request.getParameter("rememberMe")); | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
// Authenticate the user | ||||||||||||||||||||||||||||||||
Authentication auth = new UsernamePasswordAuthenticationToken(username, password); | ||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||
auth = authenticationManager.authenticate(auth); | ||||||||||||||||||||||||||||||||
SecurityContextHolder.getContext().setAuthentication(auth); | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
if (rememberMe) { | ||||||||||||||||||||||||||||||||
// Set a cookie for "Remember Me" | ||||||||||||||||||||||||||||||||
javax.servlet.http.Cookie rememberMeCookie = new javax.servlet.http.Cookie("rememberMe", username); | ||||||||||||||||||||||||||||||||
rememberMeCookie.setMaxAge(7 * 24 * 60 * 60); // 7 days | ||||||||||||||||||||||||||||||||
rememberMeCookie.setHttpOnly(true); | ||||||||||||||||||||||||||||||||
rememberMeCookie.setPath("/"); | ||||||||||||||||||||||||||||||||
response.addCookie(rememberMeCookie); | ||||||||||||||||||||||||||||||||
Check warningCode scanning / CodeQL Failure to use secure cookies Medium
Cookie is added to response without the 'secure' flag being set.
Copilot AutofixAI about 1 month ago To fix the issue, the
Suggested changeset
1
src/main/java/net/codejava/AppController.java
Copilot is powered by AI and may make mistakes. Always verify output.
Positive FeedbackNegative Feedback
Refresh and try again.
Check warningCode scanning / CodeQL HTTP response splitting Medium
This header depends on a
user-provided value Error loading related location Loading Copilot AutofixAI about 1 month ago Copilot could not generate an autofix suggestion Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support. |
||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
} catch (BadCredentialsException e) { | ||||||||||||||||||||||||||||||||
model.addAttribute("error", "Invalid username or password."); | ||||||||||||||||||||||||||||||||
return "login"; | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
// User is authenticated, redirect to landing page | ||||||||||||||||||||||||||||||||
return "redirect:/"; | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,20 +29,22 @@ protected void configure(HttpSecurity http) throws Exception { | |
.authorizeRequests() | ||
.antMatchers("/login").permitAll() | ||
.antMatchers(HttpMethod.POST, "/import").permitAll() | ||
// .anyRequest().permitAll() | ||
.anyRequest().authenticated() | ||
.and() | ||
.formLogin() | ||
// .loginPage("/login") | ||
// .loginProcessingUrl("/login") // This should match the form action in your login.html file | ||
.usernameParameter("username") | ||
.passwordParameter("password") | ||
.defaultSuccessUrl("/", true) // This is the URL to redirect to after a successful login | ||
.defaultSuccessUrl("/", true) | ||
.failureUrl("/login?error=true") | ||
.permitAll() | ||
.and() | ||
.rememberMe() | ||
.key("uniqueAndSecret") | ||
.rememberMeParameter("rememberMe") | ||
.tokenValiditySeconds(7 * 24 * 60 * 60) // 7 days | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace the magic number for token validity seconds with a well-named constant to avoid duplication and improve clarity. Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||
.and() | ||
.logout() | ||
.logoutUrl("/logout") // This is the URL to send the user to once they have logged out | ||
.logoutUrl("/logout") | ||
.invalidateHttpSession(true) | ||
.permitAll(); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
package net.codejava; | ||
|
||
import org.junit.jupiter.api.Test; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertTrue; | ||
|
||
@SpringBootTest | ||
public class JUnit5ExampleTest12 { | ||
|
||
// Global variables to control test behavior | ||
private static boolean isSearchFeatureEnabled = true; | ||
private static int maxRecordsPerPage = 20; | ||
private static String defaultSearchQuery = "Laptop"; | ||
private static String defaultItemName = "Smartphone"; | ||
private static double defaultItemPrice = 999.99; | ||
private static String testLogPrefix = "[TEST LOG] "; // New global variable | ||
|
||
@Autowired | ||
private AppController appController; | ||
|
||
@Test | ||
void testEnableSearchFeatureDefaultValue() { | ||
if (isSearchFeatureEnabled) { | ||
System.out.println(testLogPrefix + "Feature is enabled: Running testEnableSearchFeatureDefaultValue"); | ||
assertTrue(appController.getEnableSearchFeature(), testLogPrefix + "enableSearchFeature should be true by default"); | ||
} else { | ||
System.out.println(testLogPrefix + "Feature is disabled: Skipping testEnableSearchFeatureDefaultValue"); | ||
} | ||
|
||
System.out.println(testLogPrefix + "Checking additional conditions..."); | ||
System.out.println(testLogPrefix + "Test completed successfully."); | ||
System.out.println(testLogPrefix + "Logging additional information."); | ||
System.out.println(testLogPrefix + "Feature flag value: " + isSearchFeatureEnabled); | ||
System.out.println(testLogPrefix + "Default search query: " + defaultSearchQuery); | ||
System.out.println(testLogPrefix + "Default item name: " + defaultItemName); | ||
System.out.println(testLogPrefix + "Default item price: " + defaultItemPrice); | ||
System.out.println(testLogPrefix + "Max records per page: " + maxRecordsPerPage); | ||
System.out.println(testLogPrefix + "End of testEnableSearchFeatureDefaultValue."); | ||
} | ||
|
||
@Test | ||
void testMaxRecordsPerPage() { | ||
System.out.println("Max records per page: " + maxRecordsPerPage); | ||
assertEquals(20, maxRecordsPerPage, "Max records per page should be 20"); | ||
} | ||
|
||
@Test | ||
void testDefaultSearchQuery() { | ||
System.out.println("Default search query: " + defaultSearchQuery); | ||
assertEquals("Laptop", defaultSearchQuery, "Default search query should be 'Laptop'"); | ||
} | ||
|
||
@Test | ||
void testDefaultItemName() { | ||
System.out.println("Default item name: " + defaultItemName); | ||
assertEquals("Smartphone", defaultItemName, "Default item name should be 'Smartphone'"); | ||
} | ||
|
||
@Test | ||
void testDefaultItemPrice() { | ||
System.out.println("Default item price: " + defaultItemPrice); | ||
assertEquals(999.99, defaultItemPrice, "Default item price should be 999.99"); | ||
} | ||
|
||
@Test | ||
void testEnableSearchFeatureInHomePage() { | ||
if (isSearchFeatureEnabled) { | ||
System.out.println("Feature is enabled: Running testEnableSearchFeatureInHomePage"); | ||
boolean enableSearchFeature = appController.getEnableSearchFeature(); | ||
System.out.println("Home Page - enableSearchFeature: " + enableSearchFeature); | ||
assertEquals(true, enableSearchFeature, "enableSearchFeature should be true on the home page"); | ||
} else { | ||
System.out.println("Feature is disabled: Skipping testEnableSearchFeatureInHomePage"); | ||
} | ||
} | ||
|
||
@Test | ||
void testEnableSearchFeatureInNewForm() { | ||
if (isSearchFeatureEnabled) { | ||
System.out.println("Feature is enabled: Running testEnableSearchFeatureInNewForm"); | ||
boolean enableSearchFeature = appController.getEnableSearchFeature(); | ||
System.out.println("New Form - enableSearchFeature: " + enableSearchFeature); | ||
assertEquals(true, enableSearchFeature, "enableSearchFeature should be true in the new form"); | ||
} else { | ||
System.out.println("Feature is disabled: Skipping testEnableSearchFeatureInNewForm"); | ||
} | ||
} | ||
|
||
@Test | ||
void testEnableSearchFeatureInEditForm() { | ||
if (isSearchFeatureEnabled) { | ||
System.out.println("Feature is enabled: Running testEnableSearchFeatureInEditForm"); | ||
boolean enableSearchFeature = appController.getEnableSearchFeature(); | ||
System.out.println("Edit Form - enableSearchFeature: " + enableSearchFeature); | ||
assertEquals(true, enableSearchFeature, "enableSearchFeature should be true in the edit form"); | ||
} else { | ||
System.out.println("Feature is disabled: Skipping testEnableSearchFeatureInEditForm"); | ||
} | ||
} | ||
|
||
@Test | ||
void testEnableSearchFeatureInSearch() { | ||
if (isSearchFeatureEnabled) { | ||
System.out.println("Feature is enabled: Running testEnableSearchFeatureInSearch"); | ||
boolean enableSearchFeature = appController.getEnableSearchFeature(); | ||
System.out.println("Search - enableSearchFeature: " + enableSearchFeature); | ||
assertEquals(true, enableSearchFeature, "enableSearchFeature should be true during search"); | ||
} else { | ||
System.out.println("Feature is disabled: Skipping testEnableSearchFeatureInSearch"); | ||
} | ||
} | ||
|
||
@Test | ||
void testMaxRecordsPerPageInSearch() { | ||
System.out.println("Testing maxRecordsPerPage in search functionality"); | ||
assertEquals(20, maxRecordsPerPage, "Max records per page should be consistent in search functionality"); | ||
} | ||
|
||
@Test | ||
void testDefaultSearchQueryInSearch() { | ||
System.out.println("Testing defaultSearchQuery in search functionality"); | ||
assertEquals("Laptop", defaultSearchQuery, "Default search query should be consistent in search functionality"); | ||
} | ||
|
||
@Test | ||
void testDefaultItemNameInSearch() { | ||
System.out.println("Testing defaultItemName in search functionality"); | ||
assertEquals("Smartphone", defaultItemName, "Default item name should be consistent in search functionality"); | ||
} | ||
|
||
@Test | ||
void testDefaultItemPriceInSearch() { | ||
System.out.println("Testing defaultItemPrice in search functionality"); | ||
assertEquals(999.99, defaultItemPrice, "Default item price should be consistent in search functionality"); | ||
} | ||
|
||
@Test | ||
void testEnableSearchFeatureInSave() { | ||
if (isSearchFeatureEnabled) { | ||
System.out.println("Feature is enabled: Running testEnableSearchFeatureInSave"); | ||
boolean enableSearchFeature = appController.getEnableSearchFeature(); | ||
System.out.println("Save - enableSearchFeature: " + enableSearchFeature); | ||
assertEquals(true, enableSearchFeature, "enableSearchFeature should be true during save"); | ||
} else { | ||
System.out.println("Feature is disabled: Skipping testEnableSearchFeatureInSave"); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace the magic number for the cookie's max age with a named constant to improve maintainability.
Copilot uses AI. Check for mistakes.