spring security4.2.2的maven配置+spring-security配置详解+java源码+数据库设计

最近项目需要添加权限拦截,经讨论决定采用spring security4.2.2!废话少说直接上干货!

若有不正之处,请谅解和批评指正,不胜感激!!!!!

spring security 4.2.2文档:http://docs.spring.io/spring-security/site/docs/4.2.2.RELEASE/reference/htmlsingle/#el-access-web

spring security 3 中文2文档:http://www.mossle.com/docs/auth/html/index.html

需要在pom.xml里配置spring security的依赖,可以通过http://mvnrepository.com/search?q=spring+securitye查询不同版本需要的spring的版本支持。

 1   <!--spring security  -->
 2         <dependency>
 3             <groupId>org.springframework.security</groupId>
 4             <artifactId>spring-security-core</artifactId>
 5             <version>4.2.2.RELEASE</version>
 6         </dependency>
 7
 8         <dependency>
 9             <groupId>org.springframework.security</groupId>
10             <artifactId>spring-security-web</artifactId>
11             <version>4.2.2.RELEASE</version>
12         </dependency>
13
14          <dependency>
15             <groupId>org.springframework.security</groupId>
16             <artifactId>spring-security-config</artifactId>
17             <version>4.2.2.RELEASE</version>
18         </dependency>
19         <dependency>
20             <groupId>org.springframework.security</groupId>
21             <artifactId>spring-security-taglibs</artifactId>
22             <version>4.2.2.RELEASE</version>
23         </dependency>

需要在web.xml中配置Spring Security控制权限过滤器,

1   <filter>
2         <filter-name>springSecurityFilterChain</filter-name>
3         <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
4     </filter>
5     <filter-mapping>
6         <filter-name>springSecurityFilterChain</filter-name>
7         <url-pattern>/*</url-pattern>
8     </filter-mapping>  

下面最主要的就是spring-security.xml的配置了

  1 <?xml version="1.0" encoding="UTF-8"?>
  2 <beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
  3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4     xmlns="http://www.springframework.org/schema/security"
  5     xsi:schemaLocation="http://www.springframework.org/schema/beans
  6             http://www.springframework.org/schema/beans/spring-beans.xsd
  7             http://www.springframework.org/schema/security
  8             http://www.springframework.org/schema/security/spring-security.xsd" >
  9
 10     <!-- 打印调试信息,仅在开发环境中使用 -->
 11     <!-- <debug/> -->
 12
 13     <!-- 不需要被拦截的请求 -->
 14     <http pattern="/loginPage" security="none"/>
 15     <http pattern="/scripts/**" security="none"/>
 16
 17     <!--
 18         登录页面可以使用第一种:
 19         <http pattern="/login.jsp" security="none"></http>
 20         <form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?error=true" ......
 21         这种方式直接访问.jsp
 22         也可以使用Controller来控制,两种方式登录页面login.jsp的位置不一样!!!
 23         下面是第二种方式:
 24         <http pattern="/login" security="none"></http>
 25         <form-login login-page="/login" login-processing-url="/login" ......
 26         第一个配置告诉spring security,类似于/login的url请求不做过滤处理,而第二个配置信息又告诉spring security url为/login的post请求登录请求处理。正是这种冲突导致了405错误的发生。
 27         既然知道了错误原因,那么只要避免冲突就能解决这个问题:使登录页的请求和登录处理的请求不一致,然后只配置登录页的请求不做拦截处理.
 28         我采用的方法是使用默认的登录URL /login,修改登录页面跳转url为/loginPage。请自行修改代码和配置信息
 29         这样是不是就大工告成了呢?很遗憾,当你启动程序时,输出用户名和密码,不管正确与否,都会有404 Not Found等着你,这又是为什么呢?
 30         登录请求404错误
 31         首先,建议你看一下spring security自动生成的登录页源码,你会发现有如下代码
 32         <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
 33         对于什么是csrf,请自行参考网上的资料。
 34         spring security默认情况下csrf protection是开启的,由于我们的登录页没有配置csrf的相关信息,因此spring security内置的过滤器将此链接置为无效链接
 35         解决办法就是配置csrf protection为不可用状态,在配置文件中增加
 36         <csrf disabled="true"/>
 37     -->
 38
 39     <!--
 40         1、<http auto-config="true">,他可以自动配置login form,BSIC 认证和logout URL 和logout services,如果没有特殊表明,这个的默认值是false。想要自己配置则设置为"true"
 41         2、Spring Security采用的是一种就近原则,就是说当用户访问的url资源满足多个intercepter-url时,系统将使用第一个符合条件的intercept-url进行权限控制
 42      -->
 43     <http  auto-config="true" use-expressions="true">
 44         <!--
 45             另一种权限表达式:
 46             <http use-expressions="false">
 47             <intercept-url pattern=‘/**‘ access=‘ROLE_USER‘ />
 48         -->
 49         <!-- 禁用CSRF保护,默认是启用 -->
 50         <csrf disabled="true"/>
 51
 52         <anonymous enabled="false"/>
 53
 54         <!-- 基于角色认证(必须拥有ROLE_XXX角色才能访问所有/**/XXX/**资源) -->
 55         <!-- 确保对功能URL访问都需要权限 -->
 56         <intercept-url pattern="/**/add/**" access="hasRole(‘ADD‘)"/>
 57         <intercept-url pattern="/**/update/**" access="hasRole(‘UPDATE‘)"/>
 58         <intercept-url pattern="/**/delete/**" access="hasRole(‘DELETE‘)"/>
 59         <intercept-url pattern="/**/download/**" access="hasRole(‘DOWNLOAD‘)"/>
 60         <intercept-url pattern="/**/access/**" access="hasRole(‘ADMIN‘)"/>
 61
 62         <!-- Ensures that any request to our application requires the user to be authenticated  -->
 63         <intercept-url pattern="/**" access="authenticated"/>
 64
 65
 66         <!--
 67             实现免登陆验证,默认有效时间是两周,启用rememberMe之后的两周内,用户都可以直接跳过系统,直接进入系统。
 68             实际上,Spring Security中的rememberMe是依赖cookie实现的,当用户在登录时选择使用rememberMe,系统就会在登录成功后将为用户生成一个唯一标识,并将这个标识保存进cookie中
 69             Spring Security生成的cookie名称是SPRING_SECURITY_REMEMBER_ME_COOKIE,它的内容是一串加密的字符串,
 70             当用户再次访问系统时,Spring Security将从这个cookie读取用户信息,并加以验证。如果可以证实cookie有效,就会自动将用户登录到系统中,并为用户授予对应的权限。
 71         -->
 72
 73         <!--
 74             <remember-me remember-me-parameter="remember-me"
 75             data-source-ref="dataSource"/>
 76             spring security还提供了remember me的另一种相对更安全的实现机制 :在客户端的cookie中,仅保存一个无意义的加密串(与用户名、密码等敏感数据无关),然后在db中保存该加密串-用户信息的对应关系,自动登录时,用cookie中的加密串,到db中验证,如果通过,自动登录才算通过。会自动在你的数据库里创建一个表:PERSISTENT_LOGINS。
 77             如果不加data-source-ref="dataSource",会将上述信息放在内存中!
 78             作者的项目有些特殊要求,所有采用了下面的方式:登录后要在myAuthenticationSuccessHandler做特殊的处理!
 79         -->
 80         <remember-me authentication-success-handler-ref="myAuthenticationSuccessHandler"/>
 81
 82         <!--
 83             login-page : 表示用户登陆时显示我们自定义的登录页面
 84             authentication-failure-url : 登录认证失败转向的url,当用户输入的登录名和密码不正确时,系统将再次跳转到登录页面,并添加一个error=true参数作为登陆失败的标示,这个标识是我们自定义的。
 85             default-target-url : 登录认证成功转向的地址
 86          -->
 87         <form-login
 88             login-page="/loginPage"
 89             authentication-failure-url="/loginPage?error=true"
 90             authentication-success-handler-ref="myAuthenticationSuccessHandler"
 91         />
 92
 93         <!-- 登出后,返回到登陆页面 -->
 94         <!--  <logout logout-success-url="/loginPage" logout-url="/logout"/>
 95                    delete-cookies="JSESSIONID":退出删除JSESSIONID
 96         -->
 97         <logout />
 98         <!--
 99             控制同步session的过滤器
100             如果concurrency-control标签配置了error-if-maximum-exceeded="true",max-sessions="1",那么第二次登录时,是登录不了的。
101             如果error-if-maximum-exceeded="false",那么第二次是能够登录到系统的,
102             但是第一个登录的账号再次发起请求时,会跳转到expired-url配置的url中,
103             如果没有配置expired-url,则显示:
104             This session has been expired (possibly due to multiple concurrent logins being attempted as the same user).
105             翻译过来意思就是说:这个会话已经过期(可能由于多个并发登录尝试相同的用户)
106          -->
107
108         <session-management invalid-session-url="/loginPage" >
109             <concurrency-control max-sessions="1" error-if-maximum-exceeded="false" expired-url="/loginPage"/>
110         </session-management>
111
112         <!-- 指定自己的权限验证过滤器,首先走自己的的过滤器 myFilter,如果被拦截就报没有权限;
113              如果通过会走spring security自带的拦截器,即上面配置的权限配置!
114         -->
115         <custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="myFilter"/>
116     </http>
117
118     <!-- 权限认证Spring日志监听器  -->
119     <beans:bean class="org.springframework.security.authentication.event.LoggerListener"/>
120     <beans:bean class="org.springframework.security.access.event.LoggerListener"/>
121
122     <!--
123              一个自定义的filter,必须包含authenticationManager,accessDecisionManager,securityMetadataSource三个属性,
124          我们的所有控制将在这三个类中实现,解释详见具体配置。
125     -->
126     <beans:bean id="myFilter" class="com.tcbd.common.interceptor.MyFilterSecurityInterceptor" >
127         <beans:property name="authenticationManager" ref="authenticationManager" />
128         <beans:property name="accessDecisionManager" ref="myAccessDecisionManagerBean" />
129         <beans:property name="securityMetadataSource" ref="securityMetadataSource" />
130     </beans:bean>
131
132     <!-- 验证配置,实现用户认证的入口,主要实现UserDetailsService接口即可  -->
133     <authentication-manager alias="authenticationManager" >
134         <authentication-provider ref="daoAuthenticationProvider" >
135         </authentication-provider>
136     </authentication-manager>
137
138     <beans:bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
139         <beans:property name="userDetailsService" ref="myUserDetailService" />
140         <beans:property name="passwordEncoder" ref="passwordEncoder" />
141     </beans:bean>
142     <!-- spring推荐的单向加密算法 -->
143     <beans:bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
144
145     <!-- 在这个类中,读入用户的密码,角色信息,是否锁定,账号是否过期等属性信息  -->
146     <beans:bean id="myUserDetailService" class="com.tcbd.common.interceptor.MyUserDetailService" />
147
148
149     <!-- 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源 -->
150     <beans:bean id="myAccessDecisionManagerBean" class="com.tcbd.common.interceptor.MyAccessDecisionManager" ></beans:bean>
151
152     <!-- 资源源数据定义,即定义某一资源可以被哪些角色访问 -->
153     <beans:bean id="securityMetadataSource" class="com.tcbd.common.interceptor.MyFilterSecurityMetadataSource" />
154
155     <beans:bean id="myAuthenticationSuccessHandler" class="com.tcbd.common.interceptor.MyAuthenticationSuccessHandler"/>
156
157 </beans:beans>

spring security为我们提供了三种通配符。
通配符:?
示例:/admin/g?t.jsp
匹配任意一个字符,/admin/g?t.jsp可以匹配/admin/get.jsp和/admin/got.jsp或是/admin/gxt.do。不能匹配/admin/xxx.jsp。
通配符:*
示例:/admin/*.jsp
匹配任意多个字符,但不能跨越目录。/*/index.jsp可以匹配/admin/index.jsp和/user/index.jsp,但是不能匹配/index.jsp和/user/test/index.jsp。
通配符:**
示例:/**/index.jsp
可以匹配任意多个字符,可以跨越目录,可以匹配/index.jsp,/admin/index.jsp,/user/admin/index.jsp和/a/b/c/d/index.jsp

自己的拦截器:

读入用户的密码,角色信息,是否锁定,账号是否过期等属性信息 :MyUserDetailService

 1 import java.util.ArrayList;
 2 import java.util.Collection;
 3
 4 import javax.annotation.Resource;
 5
 6 import org.apache.commons.lang.StringUtils;
 7 import org.apache.log4j.Logger;
 8 import org.springframework.dao.DataAccessException;
 9 import org.springframework.security.core.GrantedAuthority;
10 import org.springframework.security.core.authority.SimpleGrantedAuthority;
11 import org.springframework.security.core.userdetails.User;
12 import org.springframework.security.core.userdetails.UserDetails;
13 import org.springframework.security.core.userdetails.UserDetailsService;
14 import org.springframework.security.core.userdetails.UsernameNotFoundException;
15
16 /**
17  * 从数据库中读入用户的密码,角色信息,是否锁定,账号是否过期等
18  *
19  */
20 public class MyUserDetailService implements UserDetailsService {
21     @Resource
22     private UserService userService;
23
24     /**
25      * 数据库交互获取用户拥有的权限角色,并设置权限
26      */
27     @Override
28     public UserDetails loadUserByUsername(String userCode) throws UsernameNotFoundException, DataAccessException {
29         // 根据登录用户名获取用户信息
30         Users user = new Users();
31         user.setUserCode(username);
32         user = userService.selectByModel(user);
33         if (null != user) {
34             // 存放权限
35             Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
36                 String action = user.getRole();
37                 if (StringUtils.isNotBlank(action)) {
38                     String[] roleaCtion = action.split(",");
39                     for (int i = 0; i < roleaCtion.length; i++) {
40                         SimpleGrantedAuthority auth = new SimpleGrantedAuthority(roleaCtion[i]);
41                         auths.add(auth);
42                     }
43                 }
44                 //spring security自带的User对象
45             User userDetails = new User(username, user.getPassword(), true, true, true, true, auths);
46             return userDetails;
47         }
48         return null;
49     }
50 }

定义某一资源可以被哪些角色访问:MyFilterSecurityMetadataSource

 1 import java.util.ArrayList;
 2 import java.util.Collection;
 3 import java.util.List;
 4 import java.util.Map;
 5
 6 import javax.servlet.http.HttpServletRequest;
 7
 8 import org.apache.log4j.Logger;
 9 import org.springframework.security.access.ConfigAttribute;
10 import org.springframework.security.access.SecurityConfig;
11 import org.springframework.security.web.FilterInvocation;
12 import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
13
14 public class MyFilterSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
15     private static Logger logger = Logger.getLogger(MyFilterSecurityMetadataSource.class);
16
17     public List<ConfigAttribute> getAttributes(Object object) {
18         FilterInvocation fi = (FilterInvocation) object;
19         HttpServletRequest request = fi.getRequest();
20         String requestUrl = fi.getRequest().getRequestURI();
21         List<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>();
22         // 所有URL对应的角色,应用启动就存放到静态资源里,得到的结果是:不同的URL下,包含的多个角色
23         Map<String, String> resRoles = Constant.URL_ROLES;
24
25         for (Map.Entry<String, String> ent : resRoles.entrySet()) {
26             String url = ent.getKey();
27             String roles = ent.getValue();
28             //根据业务写自己的匹配逻辑
29             if(requestUrl.startsWith(url)){
30                 attributes.addAll(SecurityConfig.createListFromCommaDelimitedString(roles));
31             }
32         }
33         logger.debug("【"+request.getRequestURI()+"】 roles: "+attributes);
34         return attributes;
35     }
36
37
38     public Collection<ConfigAttribute> getAllConfigAttributes() {
39         return null;
40     }
41
42     public boolean supports(Class<?> clazz) {
43         return FilterInvocation.class.isAssignableFrom(clazz);
44     }
45 }

访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源:MyAccessDecisionManager

 1 import java.util.Collection;
 2 import java.util.Iterator;
 3
 4 import org.apache.commons.logging.Log;
 5 import org.apache.commons.logging.LogFactory;
 6 import org.springframework.security.access.AccessDecisionManager;
 7 import org.springframework.security.access.AccessDeniedException;
 8 import org.springframework.security.access.ConfigAttribute;
 9 import org.springframework.security.access.SecurityConfig;
10 import org.springframework.security.authentication.InsufficientAuthenticationException;
11 import org.springframework.security.core.Authentication;
12 import org.springframework.security.core.GrantedAuthority;
13
14 /**
15  * 在这种方法中,需要与configAttributes比较验证
16  * 1、一个对象是一个URL,一个过滤器被这个URL找到权限配置,并通过这里
17  * 2、如果没有匹配相应的认证,AccessDeniedException
18  *
19  */
20 public class MyAccessDecisionManager implements AccessDecisionManager {
21
22     private static final Log logger = LogFactory.getLog(MyAccessDecisionManager.class);
23
24     /**
25      * 在这个类中,最重要的是decide方法,如果不存在对该资源的定义,直接放行; 否则,如果找到正确的角色,即认为拥有权限,并放行,否则throw
26      * new AccessDeniedException("no right");这样,就会进入上面提到的/accessDenied.jsp页面。
27      * @param authentication :当前用户所且有的角色
28      * @param object :当前请求的URL
29      * @param configAttributes :当前URL所且有的角色
30      */
31     @Override
32     public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
33             throws AccessDeniedException, InsufficientAuthenticationException {
34         // 资源所需的角色列表,如果角色列表为空,则放行!继续下一个拦截器。
35         if (configAttributes == null) {
36             return;
37         }
38         // 即将访问的资源URL,如 : /admin.jsp
39         logger.info("URL :"+object);
40         // 遍历所需的角色集合
41         Iterator<ConfigAttribute> ite = configAttributes.iterator();
42         while (ite.hasNext()) {
43             ConfigAttribute ca = ite.next();
44             // 该资源所需要的角色
45             String needRole = ((SecurityConfig) ca).getAttribute();
46             // authentication.getAuthorities()获取用户所拥有的角色列表,如:OLE_DEFULT
47             for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) {
48                 // 将资源所需要的角色与用户拥有的角色比较
49                 if (needRole.equals(grantedAuthority.getAuthority())) {
50                     // grantedAuthority is user‘s role.
51                     // 角色相同,直接放行
52                     return;
53                 }
54             }
55         }
56         // 否则,提示没有权限访问该资源
57         throw new AccessDeniedException("no right");
58     }
59
60     @Override
61     public boolean supports(ConfigAttribute attribute) {
62         return true;
63     }
64
65     @Override
66     public boolean supports(Class<?> clazz) {
67         return true;
68     }
69
70 }

拦截器核心,MyFilterSecurityInterceptor

 1 import java.io.IOException;
 2
 3 import javax.servlet.Filter;
 4 import javax.servlet.FilterChain;
 5 import javax.servlet.FilterConfig;
 6 import javax.servlet.ServletException;
 7 import javax.servlet.ServletRequest;
 8 import javax.servlet.ServletResponse;
 9
10 import org.springframework.security.access.SecurityMetadataSource;
11 import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
12 import org.springframework.security.access.intercept.InterceptorStatusToken;
13 import org.springframework.security.web.FilterInvocation;
14 import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
15
16 /**
17  *
18  */
19 public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor
20         implements Filter {
21
22     private FilterInvocationSecurityMetadataSource securityMetadataSource;
23
24     /* get、set方法 */
25     public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
26         return securityMetadataSource;
27     }
28
29     public void setSecurityMetadataSource(
30             FilterInvocationSecurityMetadataSource securityMetadataSource) {
31         this.securityMetadataSource = securityMetadataSource;
32     }
33
34     @Override
35     public Class<? extends Object> getSecureObjectClass() {
36         return FilterInvocation.class;
37     }
38
39     @Override
40     public SecurityMetadataSource obtainSecurityMetadataSource() {
41         return this.securityMetadataSource;
42     }
43
44     @Override
45     public void doFilter(ServletRequest request, ServletResponse response,
46             FilterChain chain) throws IOException, ServletException {
47
48         FilterInvocation fi = new FilterInvocation(request, response, chain);
49         invoke(fi);
50     }
51
52     public void invoke(FilterInvocation fi) throws IOException,
53             ServletException {
54         /**
55          * 最核心的代码就是@link InterceptorStatusToken token = super.beforeInvocation(fi);
56          * 它会调用我们定义的MyInvocationSecurityMetadataSource.getAttributes方法和MyAccessDecisionManager.decide方法
57          * 这一句,即在执行doFilter之前,进行权限的检查,而具体的实现已经交给@link MyAccessDecisionManager 了
58          */
59         InterceptorStatusToken token = super.beforeInvocation(fi);
60         try {
61             //继续走下一个拦截器,也就是org.springframework.security.web.access.intercept.FilterSecurityInterceptor
62             fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
63         } finally {
64             super.afterInvocation(token, null);
65         }
66     }
67
68     @Override
69     public void destroy() {
70
71     }
72
73     @Override
74     public void init(FilterConfig arg0) throws ServletException {
75
76     }
77
78 }

登录页面(需要自己改一些东西)

 1 <%@ page language="java" contentType="text/html; charset=UTF-8"
 2     pageEncoding="UTF-8"%>
 3 <%@ taglib prefix=‘fmt‘ uri="http://java.sun.com/jsp/jstl/fmt" %>
 4 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 5 <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
 6 <!DOCTYPE html>
 7 <html lang="zh-CN">
 8   <head>
 9     <meta charset="utf-8">
10     <meta http-equiv="X-UA-Compatible" content="IE=edge">
11     <meta name="viewport" content="width=device-width, initial-scale=1">
12     <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
13     <meta name="description" content="">
14     <meta name="author" content="">
15     <link rel="icon" href="/favicon.ico">
16
17     <title><fmt:message key="application.title"></fmt:message></title>
18
19     <!-- Bootstrap core CSS -->
20     <link href="/scripts/plugins/bootstrap/css/bootstrap.min.css" rel="stylesheet">
21
22     <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
23     <!-- Custom styles for this template -->
24
25     <link href="/scripts/apps/css/signin.css" rel="stylesheet">
26
27     <style type="text/css">
28     .tip {
29         font-size: 10px;
30         color: red;
31         text-align: center;
32     }
33
34     </style>
35   </head>
36
37   <body>
38     <div class="container">
39         <c:url var="loginUrl" value="/login" />
40       <form action="${loginUrl}" id="login_form" class="form-signin" method="post">
41           <div class="form-signin-heading text-center">
42             <h2 ><fmt:message key="application.title"></fmt:message></h2>
43           </div>
44           <div id="tip" class="tip"></div>
45           <c:if test="${param.error != null}">
46                 <span style="color:red">用户名或密码有误</span>
47         </c:if>
48
49         <label for="inputEmail" class="sr-only">登录帐号</label>
50         <input type="text" id="inputUserCode" name="username" class="form-control" placeholder="登录帐号"  autofocus>
51            <label for="inputPassword" class="sr-only">登录密码</label>
52            <input type="password" id="inputPassword" name="password" class="form-control" placeholder="登录密码">
53         <div class="input-group input-sm">
54           <div class="checkbox">
55             <label><input type="checkbox" id="rememberme" name="remember-me" value="true"> 下次自动登录</label>
56           </div>
57         </div>
58         <button id="login_button" class="btn btn-lg btn-primary btn-block" type="submit">登录</button>
59       </form>
60
61     </div>
62
63     <script src="/scripts/plugins/jQuery/jquery-2.2.3.min.js"></script>
64   </body>
65 </html>

在JSP中相应的操作按钮上加上如下标签,控制显示:

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%> 该标签一定要加上!!!
<sec:authorize access="hasRole(‘ADD‘)">
<a href="/XXX/add">增加</a>
</sec:authorize>

数据库设计:user表里有roleId,role表,resource-role表,resource表

时间: 2024-10-12 22:19:25

spring security4.2.2的maven配置+spring-security配置详解+java源码+数据库设计的相关文章

Servlet容器Tomcat中web.xml中url-pattern的配置详解[附带源码分析]

前言 今天研究了一下tomcat上web.xml配置文件中url-pattern的问题. 这个问题其实毕业前就困扰着我,当时忙于找工作. 找到工作之后一直忙,也就没时间顾虑这个问题了. 说到底还是自己懒了,没花时间来研究. 今天看了tomcat的部分源码 了解了这个url-pattern的机制.  下面让我一一道来. tomcat的大致结构就不说了, 毕竟自己也不是特别熟悉. 有兴趣的同学请自行查看相关资料. 等有时间了我会来补充这部分的知识的. 想要了解url-pattern的大致配置必须了解

Spring4.X + spring MVC + Mybatis3 零配置应用开发框架搭建详解(1) - 基本介绍

Spring4.X + spring MVC + Mybatis3 零配置应用开发框架搭建详解(1) - 基本介绍 spring集成 mybatis Spring4.x零配置框架搭建 两年前一直在做后台的纯Java开发,很少涉及web开发这块,最近换了个纯的互联网公司,需要做Web后台管理系统,之前都是用xml配置的项目,接触了公司Spring4.x的零配置项目,觉得非常有感觉,不仅仅配置简单,而且条理清晰,所以,这里把学习的内容记录下来,一来加深对这块技术的印象,另外准备做个简单的教程,如果给

Spring Boot 配置加载顺序详解

使用 Spring Boot 会涉及到各种各样的配置,如开发.测试.线上就至少 3 套配置信息了.Spring Boot 可以轻松的帮助我们使用相同的代码就能使开发.测试.线上环境使用不同的配置. 在 Spring Boot 里面,可以使用以下几种方式来加载配置.本章内容基于 Spring Boot 2.0 进行详解. 1.properties文件: 2.YAML文件: 3.系统环境变量: 4.命令行参数: 等等-- 我们可以在 Spring Beans 里面直接使用这些配置文件中加载的值,如:

Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解(三)

前两章我为大家详细介绍了如何搭建Maven环境.Spring MVC的流程结构.Spring MVC与Struts2的区别以及示例中的一些配置文件的分析.在这一章,我就对示例的层次结构进行说明,以及MyBatis的一些简单介绍. 本文不会对MyBatis作详细说明,大象还是假定阅读本文的朋友对MyBatis(ibatis)有最基本的了解,只有这样才能较好的理解本文的内容.关于MyBatis请查看它的官方文档及其它参考资料,本文不作详细讨论. 一.工程结构图      上面这是典型的Maven项目

Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解(一)

Spring更新到3.0之后,其MVC框架加入了一个非常不错的东西——那就是REST.它的开放式特性,与Spring的无缝集成,以及Spring框架的优秀表现,使得现在很多公司将其作为新的系统开发框架.大象根据实际的项目经验,以之前SSH2例子为基础,对其进行一次大改造,详细的为大家讲解如何实现SSM3全注解式的开发. 这次大象将采取两种构建方式,一是很多人喜欢用的MyEclipse,另一个,则是用Eclipse+Maven.这一篇,将主要讲解开发环境设置与Maven构建方式. 1. 开发环境

Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解(二)

在上一篇文章中我详细的介绍了如何搭建maven环境以及生成一个maven骨架的web项目,那么这章中我将讲述Spring MVC的流程结构,Spring MVC与Struts2的区别,以及例子中的一些配置文件的分析. 一.Spring MVC 3.0介绍 Spring MVC是一个典型的MVC框架,是Spring内置的Web框架,可以作为应用项目的展示层,继Spring 2.0对Spring MVC进行重大升级后,Spring 2.5又为Spring MVC引入了注解驱动功能,再到3.0时代,全

Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解(四)

这一章大象将详细分析web层代码,以及使用Spring MVC的注解及其用法和其它相关知识来实现控制器功能.     之前在使用Struts2实现MVC的注解时,是借助struts2-convention这个插件,如今我们使用Spring自带的spring-webmvc组件来实现同样的功能,而且比之以前更简单.另外,还省掉了整合两个框架带来的不稳定因素.     对于Spring MVC框架,我主要讲一下它的常用注解,再结合一些示例进行说明,方便大家能够快速理解.     一.Spring MV

Spring基于事件驱动模型的订阅发布模式代码实例详解

代码下载地址:http://www.zuidaima.com/share/1791499571923968.htm 原文:Spring基于事件驱动模型的订阅发布模式代码实例详解 事件驱动模型简介 事件驱动模型也就是我们常说的观察者,或者发布-订阅模型:理解它的几个关键点: 首先是一种对象间的一对多的关系:最简单的如交通信号灯,信号灯是目标(一方),行人注视着信号灯(多方): 当目标发送改变(发布),观察者(订阅者)就可以接收到改变: 观察者如何处理(如行人如何走,是快走/慢走/不走,目标不会管的

Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解(五)

这是本系列的最后一篇,主要讲一下FreeMarker模板引擎的基本概念与常用指令的使用方式.     一.FreemMarker基本概念     FreemMarker是一个用Java语言编写的模板引擎,它是一个基于模板来生成文本输出的一个工具.是除了JSP之外被使用得最多的页面模板技术之一,另一个比较有名的模板则是Velocity.     用户可以使用FreeMarker来生成所需要的内容,通常由Java提供数据模型,FreeMarker通过模板引擎渲染数据模型,这样最终得到我们想要的内容.