`
liukai
  • 浏览: 702865 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Spring Security3 - MVC 整合教程 (初识Spring Security3)

阅读更多
下面我们将实现关于Spring Security3的一系列教程.
最终的目标是整合Spring Security + Spring3MVC
完成类似于SpringSide3中mini-web的功能.

Spring Security是什么?

引用
Spring Security,这是一种基于Spring AOP和Servlet过滤器的安全框架。它提供全面的安全性解决方案,同时在Web请求级和方法调用级处理身份确认和授权。在Spring Framework基础上,Spring Security充分利用了依赖注入(DI,Dependency Injection)和面向切面技术。


关于Spring Security学习的资料.
最重要,最齐全的中文资料当然是family168的中文文档
Spring Security2参考文档

Spring Security3 参考文档

附件包含了一个很好的初入门的PDF教程.
最好是花30分钟先照着PDF上的教程一步一步的操作.
虽然没有实际的应用价值,但对初学者认识SpringSecurity3很有帮助.

我们的项目目录结构最终是:




需要添加的jar包:




我们先实现一个controller:

MainController.java

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";

	}

}



该controller有两个mapping映射:

引用
main/common
main/admin


现在我们将同过Spring Security3框架实现成功登陆的人都能访问到main/common.
但只有拥有admin权限的用户才能访问main/admin.


我们先在web.xml中开启Spring3MVC和SpringSecurity3.

web.xml

<?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>



要启用SpringSecurity3,我们需要完成以下两步:
1.在web.xml中声明DelegatingFilterProxy.

<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>


表示项目中所有路径的资源都要经过SpringSecurity.

2.导入指定的SpringSecurity配置 :spring-security.xml

关于spring-security.xml的配置.
我们把这个放到后面配置.以便更详细的讲解.

注意一点.最好是将DelegatingFilterProxy写在DispatcherServlet之前.否则
SpringSecurity可能不会正常工作.



在web.xml中我们定义servlet:spring.
按照惯例,我们必须声明一个spring-servle.xml
spring-servle.xml

<?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配置声明一个视图解析器.在控制器中会根据JSP名映射到/ WEB-INF/jsp中相应的位置.


然后创建一个applicationContext.xml.

applicationContext.xml.
<?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页面

commonpage.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>


这两个JSP对应着







当然还有登陆页面和拒绝访问页面






loginpage.jsp

<%@ 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>



deniedpage.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>你的权限不够!</h1>
	<p>只有拥有Admin权限才能访问!</p>
	<a href="/spring3-security-integration/auth/login">退出登录</a>
</body>
</html>



还有一个controller用于映射上面两个JSP页面..

LoginLogoutController.java


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";

	}
}



该controller实现了两个映射
引用
auth/login     --显示Login页面
auth/denied    --显示拒绝访问页面



最后,让我们看看spring-security.xml的配置

spring-security.xml

<?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')"/>


需要注意的是我们使用了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。


所以
<security:intercept-url pattern="/auth/login" access="permitAll"/>

表示所有的人都可以访问/auth/login.


<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"/>


表示通过 /auth/login这个映射进行登录.
如果验证失败则返回一个URL:/auth/login?error=true
如果登录成功则默认指向:/main/common



security:logout 
				invalidate-session="true" 
				logout-success-url="/auth/login" 
				logout-url="/auth/logout"/>


很简单.我们开启了session失效功能.
注销URL为:/auth/logout
注销成功后转向:/auth/login



<!-- 指定一个自定义的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接口,但我们重写了他即便于我们进行数据库操作.



DbUser.java

package org.liukai.tutorial.domain;

public class DbUser {

	private String username;
	private String password;
	private Integer access;

	 //getter/setter

}




通过一个初始化的List来模拟数据库操作.

UserDao.java

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;

	}
}




自定义UserDetailsService .可以通过继承UserDetailsService
来达到灵活的自定义UserDetailsService

关于UserDetailsService更多信息. 可以查看SpringSecurity3文档


CustomUserDetailsService.java

 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;
	}
}




最后启动服务器输入:
http://localhost:8080/spring3-security-integration/auth/login



总结
通过本教程.我们对SpringSecurity3有了进一步的认识.
主要是了解了UserDetailsService的重要作用.
以及实现了模拟自定义数据的登录.(这点很重要,很多人学习了SpringSecurity却不知道
如何自定义权限)

这次教程因为内容很多,显得比较粗糙.很多地方并没有详细的阐明.
后面的教程还是SpringSecurity.
但我们将对SpringSecurity3新推出的一些特性进行详细的说明和理解.


BTW:附件为本次教程源码.你可以下载后直接在tomcat或其他web服务器启动.也可以自行添加
maven插件启动.
  • 大小: 23.5 KB
  • 大小: 18.4 KB
  • 大小: 4.6 KB
  • 大小: 5.8 KB
  • 大小: 4.2 KB
  • 大小: 8 KB
分享到:
评论
26 楼 纵观全局 2016-07-08  
666666666666666 Mark !
25 楼 Hiderevenger 2016-06-23  
,教程很好,循序渐进,融会贯通
24 楼 AllInNature 2015-07-14  
Caused by: java.lang.NoClassDefFoundError: javax/servlet/ServletContainerInitializer为什么出现这个错误,tomcat启动不了
23 楼 2013努力实现 2015-07-01  
引用
     [i][/i]
22 楼 2047699523 2015-05-04  
Spring Security 3.x完整入门配置教程及其代码下载 http://www.zuidaima.com/share/1751865719933952.htm
21 楼 Mashiro 2015-04-15  
感谢分享.......
20 楼 huanjianmeng 2015-01-10  
You cannot use a spring-security-2.0.xsd or spring-security-3.0.xsd or spring-security-3.1.xsd schema with Spring Security 3.2. Please update your schema declarations to the 3.2 schema.
19 楼 加班伤不起 2015-01-03  
感谢分享,介绍的很直观
18 楼 spoonypussy 2014-12-25  
15楼和16楼问题,可能是引入的spring-security jar包的版本与spring-security配置文件中引入的命名空间的xsd文件的版本不一致引起的。

我自己依赖的是3.2.5版本的jar包,但命名空间空xsd文件的版本为3.0,把
http://www.springframework.org/schema/security/[color=red]spring-security-3.0.xsd[/color]
改为
http://www.springframework.org/schema/security/spring-security-3.2.xsd
就好了。
17 楼 小旋风vs 2014-11-24  
好人呀。。。555555555555555555555555
16 楼 xiexie2008 2014-08-14  
CDS_CC 写道
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: spring-security-web classes are not available. You need these to use <filter-chain-map>
Offending resource: ServletContext resource [/WEB-INF/spring-security.xml]


这是什么错误,jar 包我都加了



遇到同样的错误,怎么解决的?
15 楼 CDS_CC 2014-01-13  
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: spring-security-web classes are not available. You need these to use <filter-chain-map>
Offending resource: ServletContext resource [/WEB-INF/spring-security.xml]


这是什么错误,jar 包我都加了
14 楼 xiaoquan35 2013-12-28  
很好的帖子,给我的帮助很大,看了很多篇,感觉还是这篇言简意赅,一学就会
13 楼 liukai 2013-08-09  
ly123938248 写道
http://liukai.iteye.com/admin/blogs/972914
http://liukai.iteye.com/admin/blogs/973120
这两个网页进不去,没有权限哦。

http://liukai.iteye.com/blog/972914
http://liukai.iteye.com/blog/973120
12 楼 ly123938248 2013-08-08  
http://liukai.iteye.com/admin/blogs/972914
http://liukai.iteye.com/admin/blogs/973120
这两个网页进不去,没有权限哦。
11 楼 liukai 2013-08-02  
bewithme 写道
请问,如何实现权限和资源的完全数据库配置,而不需要在xml中配如下
    <security:intercept-url pattern="/main/admin" access="hasRole('ROLE_ADMIN')"/> 
            <security:intercept-url pattern="/main/common" access="hasRole('ROLE_USER')"/> 

的确是可以的.但是比较麻烦.可以去我的github看cmop项目.
没有用spring security3  ,太麻烦了
用的是shiro 
10 楼 bewithme 2013-08-02  
请问,如何实现权限和资源的完全数据库配置,而不需要在xml中配如下
    <security:intercept-url pattern="/main/admin" access="hasRole('ROLE_ADMIN')"/> 
            <security:intercept-url pattern="/main/common" access="hasRole('ROLE_USER')"/> 
9 楼 xly1981 2013-07-02  
简单尝试就成功了,的确是细心之作
8 楼 hekuilove 2013-06-09  
if (dbUser.getUsername().equals(username) == true) {  
                logger.debug("User found");  
                return dbUser;  
            } 


大亮 
7 楼 shiweiwei 2013-05-17  
好东东,正在学习!

相关推荐

Global site tag (gtag.js) - Google Analytics