标签:spring security 权限控制 角色控制 web访问保护
简介:spring security 实现的权限控制,可以分别保护后台方法的管理,url连接访问的控制,以及页面元素的权限控制等,
security的保护,配置有简单到复杂基本有三部:
1) 采用硬编码的方式:具体做法就是在security.xml文件中,将用户以及所拥有的权限写死,一般是为了查看环境搭建的检查状态.
2) 数据库查询用户以及权限的方式,这种方式就是在用户的表中直接存入了权限的信息,比如 role_admin,role_user这样的权限信息,取出来的时候,再将其拆分.
3) 角色权限动态配置,这种方式值得是将权限角色单独存入数据库中,与用户进行相关联,然后进行相应的设置.
下面就这三种方式进行相应的程序解析
新建web项目,导入其中的包,环境搭建就算是完了,下面一部我们开始security权限控制中方法的第一种.
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/security/*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/security/dispatcher-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <!-- 权限 --> <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> </web-app>
下面我们就开始配置mvc的配置文件,名称为dispatcher-servlet.xml的springmvc的配置文件内容如下:
<?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:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 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/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <!-- 使Spring支持自动检测组件,如注解的Controller --> <context:component-scan base-package="com"/> <aop:aspectj-autoproxy/> <!-- 开启AOP --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/jsp/" p:suffix=".jsp" /> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list > <ref bean="mappingJacksonHttpMessageConverter" /> </list> </property> </bean> <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" /> <!-- 数据库连接配置 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/power"></property> <property name="user" value="root"></property> <property name="password" value="516725"></property> <property name="minPoolSize" value="10"></property> <property name="MaxPoolSize" value="50"></property> <property name="MaxIdleTime" value="60"></property><!-- 最少空闲连接 --> <property name="acquireIncrement" value="5"></property><!-- 当连接池中的连接耗尽的时候 c3p0一次同时获取的连接数。 --> <property name="TestConnectionOnCheckout" value="true" ></property> </bean> <bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource"> <ref local="dataSource"/> </property> </bean> <!-- 事务申明 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" > <ref local="dataSource"/> </property> </bean> <!-- Aop切入点 --> <aop:config> <aop:pointcut expression="within(com.ucs.security.dao.*)" id="serviceOperaton"/> <aop:advisor advice-ref="txadvice" pointcut-ref="serviceOperaton"/> </aop:config> <tx:advice id="txadvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="delete*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> </beans>
<?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.1.xsd"> <!-- 对所有页面进行拦截,需要ROLE_USER权限 --> <http auto-config='true'> <intercept-url pattern="/**" access="ROLE_USER" /> </http> <!-- 权限配置 jimi拥有两种权限 bob拥有一种权限 --> <authentication-manager> <authentication-provider> <user-service> <user name="jimi" password="123" authorities="ROLE_USER, ROLE_ADMIN" /> <user name="bob" password="456" authorities="ROLE_USER" /> </user-service> </authentication-provider> </authentication-manager> </beans:beans>
下一步,我们开始讲解第二种,数据库的用户登陆并实现获取权限进行操作.
CREATE TABLE `user` ( `Id` int(11) NOT NULL auto_increment, `logname` varchar(255) default NULL, `password` varchar(255) default NULL, `role_ids` varchar(255) default NULL, PRIMARY KEY (`Id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
<?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.1.xsd"> <!-- 启用方法控制访问权限 用于直接拦截接口上的方法,拥有权限才能访问此方法--> <global-method-security jsr250-annotations="enabled"/> <!-- 自己写登录页面,并且登陆页面不拦截 --> <http pattern="/jsp/login.jsp" security="none" /> <!-- 配置拦截页面 --> <!-- 启用页面级权限控制 使用表达式 --> <http auto-config='true' access-denied-page="/jsp/403.jsp" use-expressions="true"> <intercept-url pattern="/**" access="hasRole('ROLE_USER')" /> <!-- 设置用户默认登录页面 --> <form-login login-page="/jsp/login.jsp"/> </http> <authentication-manager> <!-- 权限控制 引用 id是myUserDetailsService的server --> <authentication-provider user-service-ref="myUserDetailsService"/> </authentication-manager> </beans:beans>
<%@ 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>登录界面</title> </head> <body> <h3>登录界面</h3> <form action="/项目根目录/j_spring_security_check" method="post"> <table> <tr><td>User:</td><td><input type='text' name='j_username' value=''></td></tr> <tr><td>Password:</td><td><input type='password' name='j_password'/></td></tr> <tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr> </table> </form> </body> </html>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %> <%@ taglib prefix="s" uri="http://www.springframework.org/tags/form" %> <!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; utf-8"> <title>Insert title here</title> </head> <body> <h5><a href="../j_spring_security_logout">logout</a></h5> <!-- 拥有ROLE_ADMIN权限的才看的到 --> <sec:authorize access="hasRole('ROLE_ADMIN')"> <form action="#"> 账号:<input type="text" /><br/> 密码:<input type="password"/><br/> <input type="submit" value="submit"/> </form> </sec:authorize> <p/> <sec:authorize access="hasRole('ROLE_USER')"> 显示拥有ROLE_USER权限的页面<br/> <form action="#"> 账号:<input type="text" /><br/> 密码:<input type="password"/><br/> <input type="submit" value="submit"/> </form> </sec:authorize> <p/> <h5>测试方法控制访问权限</h5> <a href="addreport_admin.do">添加报表管理员</a><br/> <a href="deletereport_admin.do">删除报表管理员</a> </body> </html>
package com.ucs.security.server; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import com.ucs.security.face.SecurityTestInterface; @Controller public class SecurityTest { @Resource private SecurityTestInterface dao; @RequestMapping(value="/jsp/getinput")//查看最近收入 @ResponseBody public boolean getinput(HttpServletRequest req,HttpServletRequest res){ boolean b=dao.getinput(); return b; } @RequestMapping(value="/jsp/geoutput")//查看最近支出 @ResponseBody public boolean geoutput(HttpServletRequest req,HttpServletRequest res){ boolean b=dao.geoutput(); return b; } @RequestMapping(value="/jsp/addreport_admin")//添加报表管理员 @ResponseBody public boolean addreport_admin(HttpServletRequest req,HttpServletRequest res){ boolean b=dao.addreport_admin(); return b; } @RequestMapping(value="/jsp/deletereport_admin")//删除报表管理员 @ResponseBody public boolean deletereport_admin(HttpServletRequest req,HttpServletRequest res){ boolean b=dao.deletereport_admin(); return b; } @RequestMapping(value="/jsp/user")//普通用户登录 public ModelAndView user_login(HttpServletRequest req,HttpServletRequest res){ dao.user_login(); return new ModelAndView("user"); } }
package com.ucs.security.face; import javax.annotation.security.RolesAllowed; import com.ucs.security.pojo.Users; public interface SecurityTestInterface { boolean getinput(); boolean geoutput(); @RolesAllowed("ROLE_ADMIN")//拥有ROLE_ADMIN权限的用户才可进入此方法 boolean addreport_admin(); @RolesAllowed("ROLE_ADMIN") boolean deletereport_admin(); Users findbyUsername(String name); @RolesAllowed("ROLE_USER") void user_login(); }
package com.ucs.security.dao; import java.sql.SQLException; import javax.annotation.Resource; import org.apache.log4j.Logger; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.stereotype.Repository; import com.ucs.security.face.SecurityTestInterface; import com.ucs.security.pojo.Users; @Repository("SecurityTestDao") public class SecurityTestDao implements SecurityTestInterface{ Logger log=Logger.getLogger(SecurityTestDao.class); @Resource private JdbcTemplate jdbcTamplate; public boolean getinput() { log.info("getinput"); return true; } public boolean geoutput() { log.info("geoutput"); return true; } public boolean addreport_admin() { log.info("addreport_admin"); return true; } public boolean deletereport_admin() { log.info("deletereport_admin"); return true; } public Users findbyUsername(String name) { final Users users = new Users(); jdbcTamplate.query("SELECT * FROM USER WHERE logname = ?", new Object[] {name}, new RowCallbackHandler() { @Override public void processRow(java.sql.ResultSet rs) throws SQLException { users.setName(rs.getString("logname")); users.setPassword(rs.getString("password")); users.setRole(rs.getString("role_ids")); } }); log.info(users.getName()+" "+users.getPassword()+" "+users.getRole()); return users; } @Override public void user_login() { log.info("拥有ROLE_USER权限的方法访问:user_login"); } }
package com.ucs.security.context; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.annotation.Resource; 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 org.springframework.stereotype.Service; import com.ucs.security.face.SecurityTestInterface; import com.ucs.security.pojo.Users; /** * 在spring-security.xml中如果配置了 * <authentication-manager> <authentication-provider user-service-ref="myUserDetailsService" /> </authentication-manager> * 将会使用这个类进行权限的验证。 * * **/ @Service("myUserDetailsService") public class MyUserDetailsService implements UserDetailsService{ @Resource private SecurityTestInterface dao; //登录验证 public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException { System.out.println("show login name:"+name+" "); Users users =dao.findbyUsername(name); Set<GrantedAuthority> grantedAuths=obtionGrantedAuthorities(users); boolean enables = true; boolean accountNonExpired = true; boolean credentialsNonExpired = true; boolean accountNonLocked = true; //封装成spring security的user User userdetail = new User(users.getName(), users.getPassword(), enables, accountNonExpired, credentialsNonExpired, accountNonLocked, grantedAuths); return userdetail; } //查找用户权限 public Set<GrantedAuthority> obtionGrantedAuthorities(Users users){ String roles[] = users.getRole().split(","); Set<GrantedAuthority> authSet=new HashSet<GrantedAuthority>(); for (int i = 0; i < roles.length; i++) { authSet.add(new GrantedAuthorityImpl(roles[i])); } return authSet; } }登录的时候获取登录的用户名,然后通过数据库去查找该用户拥有的权限将权限增加到Set<GrantedAuthority>中,当然可以加多个权限进去,只要用户拥有其中一个权限就可以登录进来。
点击添加报表管理员或者删除报表管理员时候会跳到403.jsp因为没有权限去访问资源,在接口上我们设置了访问的权限:
下面我们就开始研究第三种方式,需要用将角色可访问资源链接保存到数据库,可以随时更改,也就是我们所谓的url的控制,什么鸡毛,就是数据库存放了角色权限,可以实时更改,而不再xml文件中写死.
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:spring security 权限控制 角色控制 web访问保护
原文地址:http://blog.csdn.net/u014201191/article/details/47037815