首先是 Dao 的配置文件:
application-dao.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:context="http://www.springframework.org/schema/context"
5 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 classpath*:/mapper/*.xml
30
31
32
33
34
35
36
37
38
39
40
41
42
43
这边可以看到,我们明明使用的是 Mybatis 的 ORM框架,为啥还要配置一个 jdbcTemplate?其实说来惭愧,本人比较擅长 MyBatis,所以算是强迫症一定要用这个框架,但是人家 Spring 有自己的 SpringData 的框架,而 SpringSecurityOAuth2.0的插件中,很多内容都是用 SpringData 的方式去实现的,我如果要弃用 jdbcTemplate,那我得重写所有框架内涉及的数据库操作,那太累了- -,当然啦,我这么写肯定不好,因为认证系统本身没有什么复杂逻辑和除了框架外的额外操作,所以我这么做,挺浪费资源的(占内存),大家可以不要效仿这一块,用到 MyBatis 的地方只有一个读取用户名及密码的接口,也就是说,为了一个接口,确实没有必要引入一个框架。等我掌握了 jdbcTemplate 的用法,我也会去掉这个累赘。
当然~!如果,你的认证系统,跟用户管理系统,是合在一起的情况下,那倒是没啥问题,毕竟用户管理也是有很多逻辑的,像注册呀、改密啊、绑定密保啊、修改用户信息呀,这些什么鬼的。
接着我们来配置 Service:
application-service.xml
没什么内容,看注释就知道了。
然后配置 Transaction:
application-transaction.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:tx="http://www.springframework.org/schema/tx"
4 xsi:schemaLocation="http://www.springframework.org/schema/beans5 http://www.springframework.org/schema/beans/spring-beans.xsd6 http://www.springframework.org/schema/tx7 http://www.springframework.org/schema/tx/spring-tx.xsd">
8
9
10
11
12
13
14
15
嗯...事实上,可以不用配置,因为根本用不上。
配置 Spring-mvc:
spring-mvc.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:context="http://www.springframework.org/schema/context"
5 xmlns:mvc="http://www.springframework.org/schema/mvc"
6 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
28
29
30 application/json;charset=UTF-8
31
32
33
34
35
36
37
38
39
40
41
42
43
这..也没啥可说的,全世界都这么配置的= =
再来配置一个 Mybatis 的分页插件...其实可以不用配置,因为根本用不到,除非以后有啥扩展的话:
mybatis-config.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 "http://mybatis.org/dtd/mybatis-3-config.dtd">
5
6
7
8
9
10
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
这个比较详细,因为这个比较麻烦。所以内容都写的很多,如果你不配置这个,自然对目前来说,也是可以的。
再来一个 LogBack 的配置文件,这个配置文件必须放在配置文件的根目录下,我是使用 IDEA ,maven 的方式搭建项目的,这种配置资源全部都放在 resources 文件夹下,而且文件名字还就得叫这个:
logback.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2
7
8
9
10
11
12
13
14
15 UTF-8
16
20
21
22 %n[%d{yyyy-MM-dd HH:mm:ss}] [userID:%X{userID}] [%logger{50}] %n[%-5level] %msg %n23
24
25
26
27
28
29 UTF-8
30
31 ${LOG_HOME}/${appName}.log
32
36
37
41 ${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log
42
47 365
48
51
52 100MB
53
54
55
58
59
60 %n[%d{yyyy-MM-dd HH:mm:ss}] [userID:%X{userID}] [%logger{50}] %n[%-5level] %msg %n61
62
63
64
65
71
72
76
77
78
79
80
81
这个东西我想是必须的吧,毕竟,日志应该还是有用的...虽然我整个项目中,都没有输出日志的代码,不过框架还是有日志输出的需求的。= =
还剩下最后一个配置文件,这个配置文件是 MyBatis 的逆向工程插件的配置文件,如果你有用的话,就弄一个吧
generatorConfig.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
5
6
7
9
10
11
12
13
14
15
16 connectionURL="jdbc:mysql://showings.com.cn:3306/oauth"
17 userId="root"
18 password="199176">
19
20
21
23
24
25
26
27
28
29 targetProject="src/main/java">
30
31
32
33
34
35
36
37 targetProject="src/main/resources">
38
39
40
41
42
43 targetProject="src/main/java">
44
45
46
47
48
49 enableCountByExample="false"
50 enableUpdateByExample="false"
51 enableDeleteByExample="false"
52 enableSelectByExample="false"
53 selectByExampleQueryId="false"/>
54
55
好了,最重要的:
application-security.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:sec="http://www.springframework.org/schema/security"
5 xmlns:oauth2="http://www.springframework.org/schema/security/oauth2"
6 xsi:schemaLocation="http://www.springframework.org/schema/beans7 http://www.springframework.org/schema/beans/spring-beans.xsd8 http://www.springframework.org/schema/security9 http://www.springframework.org/schema/security/spring-security-4.2.xsd10 http://www.springframework.org/schema/security/oauth211 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd">
12
13
14
15
16
17
18
19 entry-point-ref="oauth2AuthenticationEntryPoint"use-expressions="false">
20
21
22
23
24
25
26
27
28
29
30 class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"/>
31
32
33 class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler"/>
34
35
36 class="org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler"/>
37
38
39
40
41
42
43
44
45
46
47
48
49 class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
50
51
52
53
54
55
56 authorized-grant-types="password,authorization_code,refresh_token,implicit"
57 secret="web"scope="read,write"/>
58
59
60
61
62
63
64
65
66
67 class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 class="org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices">
87
88
89
90
91 user-approval-handler-ref="oauthUserApprovalHandler"
92 user-approval-page="oauth_approval"
93 error-page="oauth_error">
94
95
96
97
98
99
100
101
102
103
104
105
106
107 default-target-url="index.html"
108 login-page="login.html"login-processing-url="login"/>
109
110
111
112
113
114
115
116
117
118
119
120
121
122
这个文档很长,而且我也必须做一个讲解,否则就算配置了,估计也不知道怎么用。
我们,分段讲解:
1
2
3
这个,是告诉框架,这三块内容,不需要权限验证,任何人都可以获取,所以对这三个资源,直接绕过 SpringSecurity 框架。
1
2
3 entry-point-ref="oauth2AuthenticationEntryPoint"use-expressions="false">
4
5
6
7
8
9
10
这部分,是OAuth2.0用于获取 token 的地址,就是上面写的"/oauth/token",上面的配置内容我挑着讲解一下,首先是 “authentication-manager-ref”,这是是认证管理器的指定,意思就是,当访问这个资源的时候,我们要用特定的,专门为获取 token 的认证管理器,这么说可能不理解,那有特定的认证管理器,就肯定有普通的认证管理器,普通的认证管理器,就是之前我配置 RBAC 权限系统的时候,用户的以用户名及密码登录时的那个验证用户密码的管理器,这个是最普通的,也是必须有的管理器,相对这个管理器来说,OAuth2.0需要一个专门对“/oauth/token”这个资源(要获取的 token 本身就是一种资源),有一个认证管理器,认证的是 client-id 与对应的 client-secret,就是对访问客户端的认证,我们对客户端程序是有限制的,不是每个客户端程序都能够访问我们的接口,而是我们资源服务器授权的某个客户端才能有资格来申请,这么说可能还是不太好理解,我用现实中的例子来说明这个问题:
我们都在某些小型的网站,尤其是论坛上看到登录时,可以选择使用 QQ 登录,对吧?这也是 OAuth2.0的一个业务场景,其实这些小型网站要实现这类功能之前,必须先跟腾讯申请合作,然后腾讯会在它自己的客户端数据表中,创建一个属于这个小网站的一个 ID,对于腾讯来说,这个小网站就是一个客户端,他想要获取腾讯的一些资源,比如用户昵称及头像。那小网站 A 跟腾讯签订了合作协议,腾讯同意它作为一个客户端来访问资源(仅仅是说 token 的资源,因为这个针对客户端的授权认证,仅仅只是用来申请 token 的),但是腾讯不允许没有跟他签订合作的其他小网站来访问资源,所以那些没有申请合作的小网站,没有腾讯分发的 ID及密码,自然就不能发起访问申请。而且,OAuth2.0有一个很重要的功能,就是根据不同的客户端,可以区别对待,比如一个比较大一点的中型网站,跟腾讯有付费关系,就是所谓的哈哈,QQ 会员级别,那他跟其他没付费的小网站自然不同,腾讯能让她访问的资源内容的范围肯定也不同,所以通过不同的 client,自然就可以进行区别对待,冠冕堂皇收取 QQ 会员费啦~!哈哈
其他元素,我就不解释了,都有对应的 Bean,对应 Bean 上都有注释,主要是没啥不好理解的,所以就不需要解释了吧。
这就是刚才我说的,客户端配置,我这边是完全是写死的,因为我的网站没打算建立开放平台给别人,妈蛋,我的网站要有那个能力,大家都来我这里获取资源,我还在这里写代码作死?当然啦,我在底下有注释,用于数据库配置的方式,其实也没啥难的。这边我们可以看一下,authorized-grant-type 是认证类型,五种认证类型,可以根据需要,做一些取舍,一般,常用的是 authorization_code,这个是最常用的手法,资源服务器之间的通讯可以使用implicit,具体这几种方式怎么用,恩,回头我再写一个博客专门讲好了。
1
2
3 user-approval-handler-ref="oauthUserApprovalHandler"
4 user-approval-page="oauth_approval"
5 error-page="oauth_error">
6
7
8
9
10
11
这个呢,可以讲得也不多,就是那个 user-approval-page,我讲一下,我们在使用微信的时候,其实微信也是用的 OAuth2.0,只是没有让你输入用户密码,因为你本身就登录着微信,而微信是 Socket 连接,是收信任的链接方式,所以当你点一些小程序或者一些其他基于微信开发的一些程序的时候,就从来不用输入用户密码,但是一定会有一个提示,就是问你是否要授权微信登录,其实就是这样的一个类似的授权页面,如图:
为啥要有这个页面,好像多此一举的感觉呢?很简单咯,以防万一,一些恶意网站,在你不知情的情况下,去调用你的信息。而 error-page 就是当用户点击拒绝访问的时候,跳转的页面。
1
这个是资源 ID,定义资源服务器的,恩...其实我也不知道这个要不要加入到这里,没试过,因为这个是必须要加到资源服务器的配置文件当中的,而认证服务器要不要我还不清楚,因为我目前还没有把资源服务器的内容写起来,反正暂且先写着,如果不需要,回头再去掉就行。
1
2
3
4
5 default-target-url="index.html"
6 login-page="login.html"login-processing-url="login"/>
7
8
9
10
11
12
13
14
15
16
17
18
这个,就是用户认证系统,不管用RBAC权限管理设计,还是 OAuth2.0协议,都不可避免要输入用户密码,这部分呢就是用来定义这个的。这里有一个坑啊,就是这两个东西,必须放在最后面,因为,我们的拦截地址是拦截/**及/oauth/**,如果写在刚才申请 token 的那个/oauth/token 的配置前面,则会被覆盖,那不管怎么输入用户密码,都不会走用户验证管理器,而是都去走刚才上面说到的那个特殊的,验证client的用户验证管理器。那就不管怎样,都登录不了了= =。
好了,最后就是 Web.xml的配置了。
web.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
5 version="3.1">
6
7
8 contextConfigLocation
9 classpath*:config/application-*.xml
10
11
12 webAppRootKey
13 web.root
14
15
16 org.springframework.web.util.WebAppRootListener
17
18
19
20 org.springframework.web.context.ContextLoaderListener
21
22
23
24 CharacterEncodingFilter
25 org.springframework.web.filter.CharacterEncodingFilter
26
27 encoding
28 utf-8
29
30
31
32 CharacterEncodingFilter
33 /*
34
35
36 springSecurityFilterChain
37 org.springframework.web.filter.DelegatingFilterProxy
38
39
40 springSecurityFilterChain
41 /*
42
43
44
45 dispatcherServlet
46 org.springframework.web.servlet.DispatcherServlet
47
48 contextConfigLocation
49 classpath*:config/spring-mvc.xml
50
51 2
52
53
54 dispatcherServlet
55 /
56
57
58 login.html
59
60
这个配置很普通,没有什么复杂的。恩,关键的地方说一下,就是 welcome-file-list 这边,我设置成了 login.html,我是这么考虑的:这个认证系统吧,如果真的用起来,可能会比较频繁,所以不希望总是要经过 spirng 及 spring-mvc 来控制,就做成静态页面好了,这样可以提高些效率。而且本身登录也没有什么复杂逻辑,用不到 JSP,所以我把登录页面做成了静态页面,而且希望项目的默认访问地址,就是登录页面,因为本身这就只是一个认证系统而已,没有其他的功能。
但是看一下前面的 Security 配置中,对用户登录认证的部分的配置,我配置了登录失败的一些错误页面,
首先是“login.html?authorization_error=true”,这个是当认证失败,就是验证用户密码错误的时候,返回的页面,当然还是要回到登录页面,但是带了URL参数,还有一个就是“login.html?access_denied=true”,这个是访问拒绝的页面,就是当你没有登录就想要访问一些资源的时候,会跳转到这个页面,其实还是登录页面,只是携带参数不同,不过...本身认证系统就没有什么其他接口,所以这个可能也没啥用就是了...那反正定义一个,也好。
在 login.html 页面呢,因为是静态的,不能用 jstl 表达式来获取 URL 参数从而显示不同的提示语,但是可以使用 js 来做这个事儿,回头我再贴出 login.html 的代码。