spring-Security的作用就不多说了,大家都懂的!
假设 一个项目有2个权限一个是管理员admin,一个是普通用户user。有些网页,action是只能admin去访问,user不能访问。
有一些解决方法是选择将user访问不到的连接影藏掉,但是这样不能彻底解决,
假如我知道连接可以收到去敲连接访问到,那又有一种办法在每个方法前面加判断,这些介绍一种spring的安全框架spring-Security
spring-Security 还有很多功能是我还没发现的,因为项目中用到了权限判断就学习了下,记录下来,不对的地方希望大虾能提成来指导!
在项目中一般都已经搭好框架了的,主要在这个前提下 我说一下我学习到的!
我先建立了个测试环境(struts2 的 把spring 和 spring-Security3.0的jar导进去,为方便就没加数据库)
spring-Security下载地址(官方的有jar,demo) 点击打开链接
我建立了一个403.jsp 目的是让没有权限的用户跳到这里(里面没什么内容,就不贴代码了(内容:403.jsp 做了一个标识))
一个login.jsp 用来登录
一个welcome.jsp,namespace="/admin" 的struts2的包下的atestAction.action 只能admin访问
一个/welcomeUser.jsp 能让admin和user访问
一个namespace="/user" 的struts2的包下的utestAction.action 只能user 访问
项目图
web.xml
主要有spring的listener struts2的filter 和 spring-Security filter 过滤器
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext*.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- spring-Security 过滤器 -->
<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>
<!-- struts2 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
</web-app>
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<package name="default" extends="struts-default">
<action name="loginAction" class="com.yeshun.action.UserAction" method="login">
<result name="success">/index.jsp</result>
<result name="error">/403.jsp</result>
</action>
</package>
<package name="admin" extends="struts-default" namespace="/admin">
<action name="atestAction" class="com.yeshun.action.TestAction" method="admin">
<result name="success">/welcome.jsp</result>
</action>
</package>
<package name="user" extends="struts-default" namespace="/user">
<action name="utestAction" class="com.yeshun.action.TestAction" method="user">
<result name="success">/welcomeUser.jsp</result>
</action>
</package>
</struts>
主要spring-Security的配置文件 applicationContext-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: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/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<http access-denied-page="/403.jsp" use-expressions="true"><!-- 当访问被拒绝时,会转到403.jsp -->
<intercept-url pattern="/css/**" filters="none" />
<intercept-url pattern="/img/**" filters="none" />
<intercept-url pattern="/js/**" filters="none" />
<!-- 一般项目中都会用到 css,img,js等文件 那么在这些路径下的文件就不需要设定权限 filters="none" 就是不需要权限 -->
<intercept-url pattern="/login.jsp" filters="none" />
<intercept-url pattern="/welcome.jsp" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/admin/*.action" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/welcomeUser.jsp" access="hasAnyRole('ROLE_ADMIN','ROLE_USER')" />
<intercept-url pattern="/user/*.action" access="hasRole('ROLE_USER')" />
<!-- hasRole('ROLE_ADMIN') 表示只能ROLE_ADMIN权限可以访问 -->
<!-- hasRole('ROLE_USER') 表示只能ROLE_USER权限可以访问 -->
<!-- hasAnyRole('ROLE_ADMIN','ROLE_USER') 表示只能ROLE_ADMIN,ROLE_USER权限可以访问 -->
<!-- hasRole只能指定一个权限,hasAnyRole可以指定多个 -->
<form-login login-page="/login.jsp"
authentication-failure-url="/login.jsp?error=true"
default-target-url="/loginAction.action" />
<!-- login-page 登录界面 -->
<!-- authentication-failure-url 失败返回地址(验证失败,用户名密码错误) -->
<!-- default-target-url 成功返回地址 这里我返回到了一个action中,可以进一步操作 -->
<logout logout-success-url="/login.jsp" /> <!-- 登出跳转地址 -->
<!-- 保证一个用户同时只能登入一次
<session-management>
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
-->
</http>
<!-- 认证管理器,实现用户认证的入口,主要实现UserDetailsService接口即可 -->
<authentication-manager alias="authenticationManager">
<authentication-provider
user-service-ref="myUserDetailService">
<!-- 如果用户的密码采用加密的
<password-encoder hash="md5" />
-->
</authentication-provider>
</authentication-manager>
<beans:bean id="myUserDetailService"
class="com.yeshun.service.MyUserDetailService" />
</beans:beans>
MyUserDetailService.java 实现用户验证 ,实现UserDetailsService接口
package com.yeshun.service;
import java.util.ArrayList;
import java.util.Collection;
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;
import com.yeshun.util.Md5Util;
public class MyUserDetailService implements UserDetailsService {
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
//这里就不连接数据库了 手动验证用户 及赋予权限
/**
* UserInfo user = userDao.getUser(username);
* if(user == null){
* throw new UsernameNotFoundException("用户不存在,请重新输入!");
* }else{
* // to do
* // 根据用户名得到用户的密码 ,得到用户的权限
* }
*/
/**
* 这里默认密码
* 假如配置文件加上了<password-encoder hash="md5" />
* String password = Md5Util.MD5("123456");
*/
String password = "123456";
//给用户赋予权限,这里就手动了 项目中可以从数据库查出来
Collection<GrantedAuthority> auths=new ArrayList<GrantedAuthority>();
GrantedAuthorityImpl auth=new GrantedAuthorityImpl("ROLE_ADMIN");
auths.add(auth);
// GrantedAuthorityImpl auth1=new GrantedAuthorityImpl("ROLE_USER");
// auths.add(auth1);
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
// User(String username, String password, boolean enabled, boolean accountNonExpired,
// boolean credentialsNonExpired, boolean accountNonLocked, Collection<GrantedAuthority> authorities)
User user = new User(username,
password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, auths);
//假如 数据库是md5加密的 那在配置文件里加上<password-encoder hash="md5" />
return user;
}
}
UserAction.java 登录成功后返回到这里,可以得到user
package com.yeshun.action;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
public class UserAction extends BaseAction{
private static final long serialVersionUID = 1L;
public String login() {
//得到登录的用户
try {
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (obj instanceof User) {
User user = ((User) obj);
String username = user.getUsername();
String password = user.getPassword();
List<String> userRoles = new ArrayList<String>();
Collection<GrantedAuthority> cols = user.getAuthorities();
for (GrantedAuthority grantedAuthority : cols) {
userRoles.add(grantedAuthority.getAuthority());
}
// to do some thing ....
/**
* UserInfo userInfo = new UserInfo();
* userInfo.setUsername(username);
* userInfo.setPassword(password);
* userInfo.setRoles(userRoles);
* request.getSession().setAttribute("userInfo", userInfo);
*/
System.out.println("login success.........");
System.out.println("username:"+username);
System.out.println("password:"+password);
for (String str : userRoles) {
System.out.println("user roles :"+str);
}
}
} catch (Exception e) {
e.printStackTrace();
return ERROR;
}
return SUCCESS;
}
}
基本配置文件和java文件都好了,没写的文件里面都就一些标识
下面看登录 login.jsp (用户名随意的,密码必须是123456 简单识别)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Spring Security 3</title>
</head>
<body>
<br />
<center>
<form name="loginform" action="j_spring_security_check" method="POST" >
<table align="center" width="600" height="468"
style="background-image: url();">
<tr>
<td height="100">
</td>
<td height="100">
</td>
</tr>
<tr>
<td width="220"></td>
<td>
<font size="2"> <span style="color: black"> 用户名</span> <input id="username"
type='text' name="j_username" value="" style="width: 100px"> <span
style="color: black">密码</span> <input id="pwd" type='password'
name='j_password' value="" style="width: 100px"> <input
name="submit" type="submit" value="登录" class="btn"> </font>
</td>
</tr>
</table>
</form>
</center>
</body>
</html>
主要要记住2点
第一:登录form 的action 必须是 j_spring_security_check
第二:用户名,密码 的name 必须是 j_username,j_password
index.jsp 登录成功后的页面 主要来实现连接的访问权限
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%
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 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
This is my JSP page. <br>
<a href="admin/atestAction.action">admin action</a> <br />
<a href="welcome.jsp">welcome.jsp</a> <br />
<a href="user/utestAction.action">user action</a> <br />
<a href="welcomeUser.jsp">welcomeUser.jsp</a> <br />
<a href="j_spring_security_logout">Logout</a> <br />
</body>
</html>
这里有一个注意点: 登出的链接必须是 <a href="j_spring_security_logout">
对照项目图,别的jsp内容基本就一些识别标志
附上项目源码点击打开链接