環境:Spring 4.3.2.RELEASE + Spring Security 4.1.2.RELEASE,全註解配置,Spring MVC 已就緒。
CREATE TABLE `user` (
`username` VARCHAR(255) NOT NULL,
`password` CHAR(255) NOT NULL,
`roles` ENUM('MEMBER','MEMBER,LEADER','SUPER_ADMIN') NOT NULL DEFAULT 'MEMBER',
PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
設計說明:LEADER 角色字串包含 MEMBER,使其自動擁有會員權限;也可在程式碼中邏輯判斷。
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="sf" uri="https://www.springframework.org/tags/form"%>
<html>
<head><title>登入</title></head>
<body>
<div>
<sf:form action="${pageContext.request.contextPath}/log" method="POST" commandName="user">
<h1>登入</h1>
<c:if test="${error==true}"><p style="color:red">帳號或密碼錯誤</p></c:if>
<c:if test="${logout==true}"><p>已登出</p></c:if>
<sf:input path="username" name="user.username" placeholder="輸入帳號" /><br/>
<sf:password path="password" name="user.password" placeholder="輸入密碼" /><br/>
<input id="remember-me" name="remember-me" type="checkbox"/>
<label for="remember-me">一週內記住我</label>
<input type="submit" class="submit" value="提交">
</sf:form>
</div>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false"%>
<%@ taglib prefix="security" uri="https://www.springframework.org/security/tags" %>
<html>
<head>
<title>歡迎你,<security:authentication property="principal.username" var="username"/>${username}</title>
</head>
<body>
<security:authorize access="isAuthenticated()"><h3>登入成功!${username}</h3></security:authorize>
<security:authorize access="hasRole('MEMBER')"><p>你是 MEMBER</p></security:authorize>
<security:authorize access="hasRole('LEADER')"><p>你是 LEADER</p></security:authorize>
<sf:form id="logoutForm" action="${pageContext.request.contextPath}/logout" method="post">
<a href="#" onclick="document.getElementById('logoutForm').submit();">登出</a>
</sf:form>
</body>
</html>
@Order(2)
public class WebSecurityAppInit extends AbstractSecurityWebApplicationInitializer { }
@Configuration
@EnableWebSecurity
@ComponentScan("com.chuanzhi.workspace.service.impl.*")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired private UserDetailService userDetailService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/me").hasAnyRole("MEMBER","SUPER_ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/").permitAll()
.loginProcessingUrl("/log")
.failureForwardUrl("/?error=true")
.defaultSuccessUrl("/me")
.and()
.logout()
.logoutUrl("/logout").permitAll()
.logoutSuccessUrl("/?logout=true")
.and()
.rememberMe()
.tokenValiditySeconds(604800)
.rememberMeParameter("remember-me")
.rememberMeCookieName("workspace");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailService);
}
}
@RequestMapping(value = "/")
public String login(Model model, User user,
@RequestParam(value="error", required=false) boolean error,
@RequestParam(value="logout", required=false) boolean logout,
HttpServletRequest request) {
model.addAttribute(user);
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && !auth.getPrincipal().equals("anonymousUser") && auth.isAuthenticated()) {
return "me";
}
if (error) model.addAttribute("error", true);
if (logout) model.addAttribute("logout", true);
return "login";
}