原文地址:http://liukai.iteye.com/blog/982088html
package org.liukai.tutorial.controller; import org.apache.log4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller @RequestMapping("/main") public class MainController { protected static Logger logger = Logger.getLogger("controller"); /** * 跳轉到commonpage頁面 * * @return */ @RequestMapping(value = "/common", method = RequestMethod.GET) public String getCommonPage() { logger.debug("Received request to show common page"); return "commonpage"; } /** * 跳轉到adminpage頁面 * * @return */ @RequestMapping(value = "/admin", method = RequestMethod.GET) public String getAadminPage() { logger.debug("Received request to show admin page"); return "adminpage"; } }
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <!-- SpringSecurity必須的filter --> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring-security.xml /WEB-INF/applicationContext.xml </param-value> </context-param> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
<filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
表示項目中全部路徑的資源都要通過SpringSecurity.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- 定義一個視圖解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" /> </beans>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <!-- 激活spring的註解. --> <context:annotation-config /> <!-- 掃描註解組件而且自動的注入spring beans中. 例如,他會掃描@Controller 和@Service下的文件.因此確保此base-package設置正確. --> <context:component-scan base-package="org.liukai.tutorial" /> <!-- 配置註解驅動的Spring MVC Controller 的編程模型.注:次標籤只在 Servlet MVC工做! --> <mvc:annotation-driven /> </beans>
接着是建立JSP頁面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Common Page</h1>
<p>每一個人都能訪問的頁面.</p>
<a href="/spring3-security-integration/main/admin"> Go AdminPage </a>
<br />
<a href="/spring3-security-integration/auth/login">退出登陸</a>
</body>
</html>
adminpage.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Admin Page</h1>
<p>管理員頁面</p>
<a href="/spring3-security-integration/auth/login">退出登陸</a>
</body>
</html>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%> <%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h1>Login</h1> <div id="login-error">${error}</div> <form action="../j_spring_security_check" method="post"> <p> <label for="j_username">Username</label> <input id="j_username" name="j_username" type="text" /> </p> <p> <label for="j_password">Password</label> <input id="j_password" name="j_password" type="password" /> </p> <input type="submit" value="Login" /> </form> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h1>你的權限不夠!</h1> <p>只有擁有Admin權限才能訪問!</p> <a href="/spring3-security-integration/auth/login">退出登陸</a> </body> </html>
還有一個controller用於映射上面兩個JSP頁面..
package org.liukai.tutorial.controller; import org.apache.log4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @Controller @RequestMapping("auth") public class LoginLogoutController { protected static Logger logger = Logger.getLogger("controller"); /** * 指向登陸頁面 */ @RequestMapping(value = "/login", method = RequestMethod.GET) public String getLoginPage( @RequestParam(value = "error", required = false) boolean error, ModelMap model) { logger.debug("Received request to show login page"); if (error == true) { // Assign an error message model.put("error", "You have entered an invalid username or password!"); } else { model.put("error", ""); } return "loginpage"; } /** * 指定無訪問額權限頁面 * * @return */ @RequestMapping(value = "/denied", method = RequestMethod.GET) public String getDeniedPage() { logger.debug("Received request to show denied page"); return "deniedpage"; } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"> <!-- Spring-Security 的配置 --> <!-- 注意開啓use-expressions.表示開啓表達式. see:http://www.family168.com/tutorial/springsecurity3/html/el-access.html --> <security:http auto-config="true" use-expressions="true" access-denied-page="/auth/denied" > <security:intercept-url pattern="/auth/login" access="permitAll"/> <security:intercept-url pattern="/main/admin" access="hasRole('ROLE_ADMIN')"/> <security:intercept-url pattern="/main/common" access="hasRole('ROLE_USER')"/> <security:form-login login-page="/auth/login" authentication-failure-url="/auth/login?error=true" default-target-url="/main/common"/> <security:logout invalidate-session="true" logout-success-url="/auth/login" logout-url="/auth/logout"/> </security:http> <!-- 指定一個自定義的authentication-manager :customUserDetailsService --> <security:authentication-manager> <security:authentication-provider user-service-ref="customUserDetailsService"> <security:password-encoder ref="passwordEncoder"/> </security:authentication-provider> </security:authentication-manager> <!-- 對密碼進行MD5編碼 --> <bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/> <!-- 經過 customUserDetailsService,Spring會自動的用戶的訪問級別. 也能夠理解成:之後咱們和數據庫操做就是經過customUserDetailsService來進行關聯. --> <bean id="customUserDetailsService" class="org.liukai.tutorial.service.CustomUserDetailsService"/> </beans>
在配置中咱們能夠看到三個URL對應的三個權限
<security:intercept-url pattern="/auth/login" access="permitAll"/> <security:intercept-url pattern="/main/admin" access="hasRole('ROLE_ADMIN')"/> <security:intercept-url pattern="/main/common" access="hasRole('ROLE_USER')"/>
<security:intercept-url pattern="/auth/login" access="permitAll"/>
<security:form-login login-page="/auth/login" authentication-failure-url="/auth/login?error=true" default-target-url="/main/common"/>
<security:logout
invalidate-session="true"
logout-success-url="/auth/login"
logout-url="/auth/logout"/>
<!-- 指定一個自定義的authentication-manager :customUserDetailsService --> <security:authentication-manager> <security:authentication-provider user-service-ref="customUserDetailsService"> <security:password-encoder ref="passwordEncoder"/> </security:authentication-provider> </security:authentication-manager> <!-- 對密碼進行MD5編碼 --> <bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/> <!-- 經過 customUserDetailsService,Spring會自動的用戶的訪問級別. 也能夠理解成:之後咱們和數據庫操做就是經過customUserDetailsService來進行關聯. --> <bean id="customUserDetailsService" class="org.liukai.tutorial.service.CustomUserDetailsService"/>
一個自定義的CustomUserDetailsService,是實現SpringSecurity的UserDetailsService接口,但咱們重寫了他即使於咱們進行數據庫操做.
package org.liukai.tutorial.dao; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import org.liukai.tutorial.domain.DbUser; public class UserDao { protected static Logger logger = Logger.getLogger("dao"); public DbUser getDatabase(String username) { List<DbUser> users = internalDatabase(); for (DbUser dbUser : users) { if (dbUser.getUsername().equals(username) == true) { logger.debug("User found"); return dbUser; } } logger.error("User does not exist!"); throw new RuntimeException("User does not exist!"); } /** * 初始化數據 */ private List<DbUser> internalDatabase() { List<DbUser> users = new ArrayList<DbUser>(); DbUser user = null; user = new DbUser(); user.setUsername("admin"); // "admin"通過MD5加密後 user.setPassword("21232f297a57a5a743894a0e4a801fc3"); user.setAccess(1); users.add(user); user = new DbUser(); user.setUsername("user"); // "user"通過MD5加密後 user.setPassword("ee11cbb19052e40b07aac0ca060c23ee"); user.setAccess(2); users.add(user); return users; } }
package org.liukai.tutorial.service; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.apache.log4j.Logger; import org.liukai.tutorial.dao.UserDao; import org.liukai.tutorial.domain.DbUser; import org.springframework.dao.DataAccessException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.GrantedAuthorityImpl; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; /** * 一個自定義的service用來和數據庫進行操做. 即之後咱們要經過數據庫保存權限.則須要咱們繼承UserDetailsService * * @author liukai * */ public class CustomUserDetailsService implements UserDetailsService { protected static Logger logger = Logger.getLogger("service"); private UserDao userDAO = new UserDao(); public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { UserDetails user = null; try { // 搜索數據庫以匹配用戶登陸名. // 咱們能夠經過dao使用JDBC來訪問數據庫 DbUser dbUser = userDAO.getDatabase(username); // Populate the Spring User object with details from the dbUser // Here we just pass the username, password, and access level // getAuthorities() will translate the access level to the correct // role type user = new User(dbUser.getUsername(), dbUser.getPassword() .toLowerCase(), true, true, true, true, getAuthorities(dbUser.getAccess())); } catch (Exception e) { logger.error("Error in retrieving user"); throw new UsernameNotFoundException("Error in retrieving user"); } return user; } /** * 得到訪問角色權限 * * @param access * @return */ public Collection<GrantedAuthority> getAuthorities(Integer access) { List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(2); // 全部的用戶默認擁有ROLE_USER權限 logger.debug("Grant ROLE_USER to this user"); authList.add(new GrantedAuthorityImpl("ROLE_USER")); // 若是參數access爲1.則擁有ROLE_ADMIN權限 if (access.compareTo(1) == 0) { logger.debug("Grant ROLE_ADMIN to this user"); authList.add(new GrantedAuthorityImpl("ROLE_ADMIN")); } return authList; } }