spring security整合spring mvc

感谢原文出处:http://liukai.iteye.com/blog/982088/


该项目为maven项目,请先学习maven


pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.wyc</groupId>
  <artifactId>SpringSecurity</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>SpringSecurity Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>test</scope>
    </dependency>
     <!-- http://mvnrepository.com/artifact/jstl/jstl -->
	<dependency>
	    <groupId>jstl</groupId>
	    <artifactId>jstl</artifactId>
	    <version>1.1.2</version>
	</dependency>
    <!-- http://mvnrepository.com/artifact/taglibs/standard -->
	<dependency>
	    <groupId>taglibs</groupId>
	    <artifactId>standard</artifactId>
	    <version>1.1.2</version>
	</dependency>
    <!-- http://mvnrepository.com/artifact/org.springframework/spring-core -->
	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-core</artifactId>
	    <version>4.2.6.RELEASE</version>
	</dependency>
	<!-- http://mvnrepository.com/artifact/org.springframework/spring-context -->
	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-context</artifactId>
	    <version>4.2.6.RELEASE</version>
	</dependency>
	<!-- http://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-webmvc</artifactId>
	    <version>4.2.6.RELEASE</version>
	</dependency>
	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-jdbc</artifactId>
	    <version>4.2.6.RELEASE</version>
	</dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
        <version>4.1.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>4.1.0.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>4.3.2.RELEASE</version>
</dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>4.3.2.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.8.9</version>
</dependency>

    <dependency>
	    <groupId>javax.servlet</groupId>
	    <artifactId>javax.servlet-api</artifactId>
	    <version>3.0.1</version>
	    <!-- 只在编译和测试时运行 -->
	    <scope>provided</scope>
	</dependency>
	<dependency>
	    <groupId>mysql</groupId>
	    <artifactId>mysql-connector-java</artifactId>
	    <version>5.1.28</version>
	</dependency>
  </dependencies>
  <build>
    <finalName>SpringSecurity</finalName>
     <plugins>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
	          <artifactId>tomcat7-maven-plugin</artifactId>
	          <version>2.2</version>
        </plugin>
    </plugins>
  </build>
</project>

web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
   <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
			/WEB-INF/spring-servlet.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>

要想启用spring security,必须在web.xml中加入以下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>

加载配置文件,其中,spring-security.xml为spring security的配置文件,applicationContext.xml为spring配置文件

<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			/WEB-INF/spring-security.xml
			/WEB-INF/applicationContext.xml
			/WEB-INF/spring-servlet.xml
		</param-value>
	</context-param>


spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/security
		http://www.springframework.org/schema/security/spring-security.xsd">
		<!-- <beans:import resource="/spring-database.xml"/> -->
		<http use-expressions="true" auto-config="true">
		    <intercept-url pattern="/auth/login" access="permitAll"/>
		    <intercept-url pattern="/test/admin" access="hasRole('ROLE_ADMIN')"/>
		    <intercept-url pattern="/test/common" access="hasRole('ROLE_USER')"/>
		    <form-login login-page="/auth/login"
		        authentication-failure-url="/auth/login?error=true"
		        login-processing-url="/check_action"
		        default-target-url="/test/common"
		        always-use-default-target="true"
		        username-parameter="username"
		        password-parameter="password"/>
		    <logout logout-success-url="/auth/login"
		        invalidate-session="true"
		        logout-url="/auth/logout"/>
		    <!-- <access-denied-handler error-page="/auth/denied"/> -->
		    <!-- <session-management>
		        <concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>
		    </session-management> -->
		</http>
		<authentication-manager>
		    <authentication-provider user-service-ref="customerUserDetailService">
				<!-- <jdbc-user-service data-source-ref="dataSource" 
				    users-by-username-query="select username username,password password,enabled enabled from _user where username=?"
				    authorities-by-username-query="select username username,role role from _user_role where username=?"/> -->
		    </authentication-provider>
		</authentication-manager>
		
		<beans:bean id="customerUserDetailService" class="com.wyc.service.CustomerUserDetailsService"></beans:bean>
</beans:beans>


控制访问权限:
<intercept-url pattern="/auth/login" access="permitAll"/>
<intercept-url pattern="/test/admin" access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/test/common" access="hasRole('ROLE_USER')"/>
需要注意的是我们使用了 SpringEL表达式 来指定角色的访问. 
以下是表达式对应的用法.

表达式 说明 
hasRole([role]) 返回 true 如果当前主体拥有特定角色。 
hasAnyRole([role1,role2]) 返回 true 如果当前主体拥有任何一个提供的角色 (使用逗号分隔的字符串队列) 
principal 允许直接访问主体对象,表示当前用户 
authentication 允许直接访问当前 Authentication对象 从SecurityContext中获得 
permitAll 一直返回true 
denyAll 一直返回false 
isAnonymous() 如果用户是一个匿名登录的用户 就会返回 true 
isRememberMe() 如果用户是通过remember-me 登录的用户 就会返回 true 
isAuthenticated() 如果用户不是匿名用户就会返回true 
isFullyAuthenticated() 如果用户不是通过匿名也不是通过remember-me登录的用户时, 就会返回true。


自定义登录页面配置

<form-login login-page="/auth/login"
		        authentication-failure-url="/auth/login?error=true"
		        login-processing-url="/check_action"
		        default-target-url="/test/common"
		        always-use-default-target="true"
		        username-parameter="username"
		        password-parameter="password"/>

其中,login-page属性配置自定义的登录界面url,此处url指向所有人均可访问的/auth/login,这是controller中方法,指向登录页面,详情可看后文

authentication-failure属性配置的是登录失败的处理结果url,此处登录失败跳转至登录页面,并且附加error参数

login-proccessing-url属性对应登录页面表单的form中的action属性值

default-target-url属性配置默认的登录成功后的页面

always-use-default-target属性可能配置的是无论用户从哪个页面进入登录界面,最后的结果都是到达default-target-url的界面(有时候从某个页面进入登录界面,登录成功后会跳转至登录前的页面),以上俩个属性的作用纯属个人理解,文档中原文如下:

If a form login isn’t prompted by an attempt to access a protected resource, the default-target-url option comes into play. 
This is the URL the user will be taken to after successfully logging in, and defaults to "/". 
You can also configure things so that the user always ends up at this page (regardless of whether the login was "on-demand" 
or they explicitly chose to log in) by setting the always-use-default-target attribute to "true". 
This is useful if your application always requires that the user starts at a "home" page
username-parameter对应表单中用户名输入框的name属性值

同理,password-parameter对应表单中密码输入框的name属性值


配置注销账户:

<logout logout-success-url="/auth/login"
		        invalidate-session="true"
		        logout-url="/auth/logout"/>
invalidate-session配置的是 开启了session失效功能. 

配置默认无权限页面

<access-denied-handler error-page="/auth/denied"/>


配置单点登录,前一个用户登录之后,同一个账户无法再次登录
<session-management>
		        <concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>
		    </session-management>


一个自定义的CustomUserDetailsService,是实现SpringSecurity的UserDetailsService接口,但我们重写了他即便于我们进行数据库操作. 
<authentication-manager>
		    <authentication-provider user-service-ref="customerUserDetailService">
				<!-- <jdbc-user-service data-source-ref="dataSource" 
				    users-by-username-query="select username username,password password,enabled enabled from _user where username=?"
				    authorities-by-username-query="select username username,role role from _user_role where username=?"/> -->
		    </authentication-provider>
		</authentication-manager>


spring-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:beans="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.1.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.1.xsd
	http://www.springframework.org/schema/mvc
	http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
	<beans:bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	    <property name="prefix" value="/"></property>
	    <property name="suffix" value=".jsp"></property>
	</beans:bean>
</beans:beans>
配置jsp页面的访问路径及后缀(因为我们在controller中只返回jsp页面的名称)


applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:beans="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.1.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.1.xsd
	http://www.springframework.org/schema/mvc
	http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
	<context:annotation-config/>
	<context:component-scan base-package="com.wyc"></context:component-scan>
	<mvc:annotation-driven/>
</beans:beans>
context:annotation-config开启注解配置

context:component-scan配置需要扫描的包

mvc:annotation-driven开启注解驱动


TestController.java

package com.wyc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@RequestMapping("/test")
@Controller
public class TestController {

	@RequestMapping(value = "/common",method = RequestMethod.GET)
	public String common(){
		return "common";
	}
	
	@RequestMapping(value = "/admin",method = RequestMethod.GET)
	public String admin(){
		return "admin";
	}
	
}
此处勿加上responseBody注解,加入后的结果:

以tom身份登录的结果:



LoginLogoutController.java

package com.wyc.controller;

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;
import org.springframework.web.bind.annotation.ResponseBody;

@RequestMapping("/auth")
@Controller
public class LoginLogoutController {

	@RequestMapping(value ="/login",method = RequestMethod.GET)
	public String login(@RequestParam(value= "error",required = false) boolean error,ModelMap model){
		if(error){
			model.put("error", "用户名或密码错误");
		}else{
			model.put("error","");
		}
		return "login";
	}
	
	@RequestMapping(value = "denied" , method = RequestMethod.GET)
	public String denied(){
		return "accessDenied";
	}
}

DbUser.java

package com.wyc.model;

public class DbUser {

	private String username;
	private String password;
	private Integer access;
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public Integer getAccess() {
		return access;
	}
	public void setAccess(Integer access) {
		this.access = access;
	}
	
	
}

UserDao.java

package com.wyc.dao;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Repository;

import com.wyc.model.DbUser;

@Repository("userDao")
public class UserDao {

	public DbUser getDatabase(String username){
		List<DbUser> dbUsers = internalDb();
		for(DbUser dbUser : dbUsers){
			if(dbUser.getUsername().equals(username)){
				return dbUser;
			}
		}
		
		throw new RuntimeException("user is not exist");
	}

	private List<DbUser> internalDb() {
		List<DbUser> dbUsers = new ArrayList<DbUser>();
		DbUser dbUser = new DbUser();
		dbUser.setUsername("tom");
		dbUser.setPassword("tom");
		dbUser.setAccess(1);
		dbUsers.add(dbUser);
		
		dbUser = new DbUser();
		dbUser.setUsername("mike");
		dbUser.setPassword("mike");
		dbUser.setAccess(2);
		dbUsers.add(dbUser);
		return dbUsers;
	}
	
}
CustomerUserDetailsService.java

package com.wyc.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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;

import com.wyc.dao.UserDao;
import com.wyc.model.DbUser;

public class CustomerUserDetailsService implements UserDetailsService{

	@Autowired
	private UserDao userDao;
	@Override
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException {
		UserDetails userDetails = null;
		try{
			DbUser dbUser = userDao.getDatabase(username);
			userDetails = new User(dbUser.getUsername(), dbUser.getPassword().toLowerCase(), 
					true, true, true, true, getAuthorities(dbUser.getAccess()));
			
		}catch(Exception e){
			throw new UsernameNotFoundException("Error in retrieving user");
		}
		return userDetails;
	}
	private Collection<GrantedAuthority> getAuthorities(Integer access) {
		List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
		//每个用户都具有ROLE_USER权限
		authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
		 // 如果参数access为1.则拥有ROLE_ADMIN权限  
        if (access.compareTo(1) == 0) {  
            authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));  
        }  
  
        return authorities; 
	}

}


login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"  isELIgnored="false"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core"  prefix="c"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'login.jsp' starting page</title>
    
  </head>
  
  <body>
    <form method="post" action="<c:url value='check_action' />">
    	<input type="text" name="username">
    	<input type="password" name="password">
    	<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    	<input type="submit" value="提交">
    </form>
  </body>
</html>


common.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'success.jsp' starting page</title>
    
	
  </head>
  
  <body>
    每个人都可以访问的页面
    <a href = "<%=basePath %>test/admin">管理员界面</a>
    <a href = "<%=basePath %>auth/login">退出登录</a>
  </body>
</html>

admin.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'success.jsp' starting page</title>
    
	
  </head>
  
  <body>
    管理员界面
    <a href = "<%=basePath %>auth/login">退出登录</a>
  </body>
</html>

accessDenied.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'success.jsp' starting page</title>
    
	
  </head>
  
  <body>
    权限不足
    <a href= "<%=basePath %>auth/login">退出登录</a>
  </body>
</html>

至此,代码完毕

以下是结果:

使用tom登录:


点击管理员界面:

mike登录后点击管理员界面(此处无权限配置被注释):




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值