JAVA b2b2c電子商務SpringCloud分散式微服務spring-security-基本
一、簡介
Web應用的安全管理,主要包括兩個方面的內容:身份認證、使用者授權,此處使用spring-cloud-security來說明。
二、依賴管理
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity4</artifactId> </dependency>
|
三、安全策略配置
Spring Security已經大體實現了,我們這裡只是需要一些配置與引用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 |
package
com.example.demo.config; import
com.example.demo.utils.security.CustomUserService; import
com.example.demo.utils.security.LoginSuccessHandler; import
com.example.demo.utils.security.MyFilterSecurityInterceptor; import
com.example.demo.utils.security.SecuritySettings; import
org.apache.commons.lang3.StringUtils; import
org.springframework.beans.factory.annotation.Autowired; import
org.springframework.context.annotation.Bean; import
org.springframework.context.annotation.Configuration; import
org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import
org.springframework.security.config.annotation.web.builders.HttpSecurity; import
org.springframework.security.config.annotation.web.builders.WebSecurity; import
org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import
org.springframework.security.core.userdetails.UserDetailsService; import
org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import
org.springframework.security.web.authentication.AuthenticationSuccessHandler; import
org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; /**
* Security安全配置
*
* @Author: 我愛大金子
* @Description: Security安全配置
* @Date: Create in 15:20 2017/7/5
*/ @Configuration @EnableWebSecurity public
class
WebSecurityConfig
extends
WebSecurityConfigurerAdapter {
@Autowired
private
CustomFilterSecurityInterceptor customFilterSecurityInterceptor;
// 許可權管理過濾器
@Autowired
private
SecuritySettings securitySettings;
// 自定義安全配置類
/**註冊UserDetailsService的bean*/
@Bean
public
UserDetailsService customUserService(){
return
new
CustomUserService();
}
/**登入認證*/
@Override
protected
void
configure(AuthenticationManagerBuilder auth)
throws
Exception {
auth.userDetailsService(customUserService());
//userDetailsService驗證
}
/***設定不攔截規則*/
@Override
public
void
configure(WebSecurity web)
throws
Exception {
web.ignoring().antMatchers(
"/js/**"
,
"/css/**"
,
"/images/**"
,
"/druid/**"
);
}
/**安全策略配置*/
@Override
protected
void
configure(HttpSecurity http)
throws
Exception {
// 設定遊客可以訪問的URI
if
(StringUtils.isNotBlank(securitySettings.getPermitall())) {
http.authorizeRequests().antMatchers(securitySettings.getPermitall().split(
","
)).permitAll();
}
http.authorizeRequests()
.anyRequest().authenticated()
//任何請求,登入後可以訪問
// 配置登入URI、登入失敗跳轉URI與登入成功後預設跳轉URI
.and().formLogin().loginPage(
"/login"
).failureUrl(
"/login?error"
).permitAll().defaultSuccessUrl(
"/"
,
true
).successHandler(loginSuccessHandler())
// 登出行為任意訪問
.and().logout().permitAll()
// 設定拒絕訪問的提示URI
.and().exceptionHandling().accessDeniedPage(
"/login?illegal"
)
;
http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.
class
);
}
/**登入成功處理器*/
private
AuthenticationSuccessHandler loginSuccessHandler() {
return
new
LoginSuccessHandler();
} } |
說明:
loginPage:設定一個實驗自定義的登入URI
loginSuccessHandler:設定自定義的登入處理器
permitAll:是允許訪問
accessDeniedPage:配置拒絕訪問的提示URI
antMatchers:對URI的配置
瞭解springcloud架構可以加求求:三五三六二四七二五九
假設我要管理員才可以訪問admin資料夾下的內容,如:.antMatchers("/admin/**").hasRole("ROLE_ADMIN"),
也可以設定admin資料夾下的檔案可以有多個角色來訪問,如:.antMatchers("/admin/**").hasAnyRole("ROLE_ADMIN","ROLE_USER")
也可以透過hasIpAddress來指定某一個ip可以訪問該資源,寫法如下.antMatchers("/admin/**").hasIpAddress("210.210.210.210")
3.1、自定義安全配置類
為是更方便的使用springSecurity,我們自定義一個許可權的配置類,如配置登入的URI、遊客訪問的URI等配置項
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 |
package
com.example.demo.utils.security; import
org.springframework.boot.context.properties.ConfigurationProperties; import
org.springframework.context.annotation.Configuration; /**
* 自定義安全配置類
*
* @Author: 我愛大金子
* @Description: 自定義安全配置類
* @Date: Create in 9:45 2017/7/6
*/ @Configuration @ConfigurationProperties
(prefix =
"securityConfig"
) public
class
SecuritySettings {
/**允許訪問的URL,多個用逗號分隔*/
private
String permitall;
public
String getPermitall() {
return
permitall;
}
public
void
setPermitall(String permitall) {
this
.permitall = permitall;
} } |
3.2、登入成功處理器
登入成功後,如果需要對使用者的行為做一些記錄或者執行其它操作,則可以使用登入成功處理器。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 |
package
com.example.demo.utils.security; import
com.example.demo.pojo.SysUser; import
org.springframework.security.core.Authentication; import
org.springframework.security.core.userdetails.User; import
org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import
javax.servlet.ServletException; import
javax.servlet.http.HttpServletRequest; import
javax.servlet.http.HttpServletResponse; import
java.io.IOException; /**
* 登入成功處理器
*
* @Author: 我愛大金子
* @Description: 登入成功處理器
* @Date: Create in 11:35 2017/7/6
*/ public
class
LoginSuccessHandler
extends
SavedRequestAwareAuthenticationSuccessHandler {
@Override
public
void
onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws
ServletException, IOException {
User userDetails = (User) authentication.getPrincipal();
System.out.println(
"登入使用者:username="
+ userDetails.getUsername() +
", uri="
+ request.getContextPath());
super
.onAuthenticationSuccess(request, response, authentication);
} } |
3.3、springMVC 配置(訪問 /login 轉向 login.html 頁面)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 |
package
com.example.demo.config; import
org.springframework.context.annotation.Configuration; import
org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import
org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /**
* springMVC 配置(註冊訪問 /login 轉向 login.html 頁面)
*
* @Author: 我愛大金子
* @Description: springMVC 配置(註冊訪問 /login 轉向 login.html 頁面)
* @Date: Create in 16:24 2017/7/5
*/ @Configuration public
class
WebMvcConfig
extends
WebMvcConfigurerAdapter {
@Override
public
void
addViewControllers(ViewControllerRegistry registry) {
registry.addViewController(
"/login"
).setViewName(
"login"
);
} } |
四、登入認證
在安全策略配置程式碼中有,主要看自定義的CustomUserService,此類實現了UserDetailsService介面,重寫了loadUserByUsername方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
49 |
package
com.example.demo.utils.security; import
com.example.demo.dao.SysPermissionDao; import
com.example.demo.dao.SysUserDao; import
com.example.demo.pojo.SysPermission; import
org.springframework.security.core.userdetails.User; import
com.example.demo.pojo.SysUser; import
org.springframework.beans.factory.annotation.Autowired; import
org.springframework.security.core.GrantedAuthority; import
org.springframework.security.core.authority.SimpleGrantedAuthority; import
org.springframework.security.core.userdetails.UserDetails; import
org.springframework.security.core.userdetails.UserDetailsService; import
org.springframework.security.core.userdetails.UsernameNotFoundException; import
java.util.ArrayList; import
java.util.List; /**
* 自定義UserDetailsService,將使用者許可權交給springsecurity進行管控
*
* @Author: 我愛大金子
* @Description: 將使用者許可權交給Springsecurity進行管控
* @Date: Create in 16:19 2017/7/5
*/ public
class
CustomUserService
implements
UserDetailsService {
@Autowired
private
SysUserDao sysUserDao;
@Autowired
private
SysPermissionDao sysPermissionDao;
@Override
public
UserDetails loadUserByUsername(String username) {
SysUser user = sysUserDao.findByUserName(username);
if
(user !=
null
) {
List<SysPermission> permissions = sysPermissionDao.findByAdminUserId(user.getId());
List<GrantedAuthority> grantedAuthorities =
new
ArrayList <>();
for
(SysPermission permission : permissions) {
if
(permission !=
null
&& permission.getName()!=
null
) {
GrantedAuthority grantedAuthority =
new
SimpleGrantedAuthority(permission.getName());
//1:此處將許可權資訊新增到 GrantedAuthority 物件中,在後面進行全許可權驗證時會使用GrantedAuthority 物件。
grantedAuthorities.add(grantedAuthority);
}
}
return
new
User(user.getUsername(), user.getPassword(), grantedAuthorities);
}
else
{
throw
new
UsernameNotFoundException(
"admin: "
+ username +
" do not exist!"
);
}
} } |
五、許可權管理
在Security安全配置類中使用了許可權管理過濾器CustomFilterSecurityInterceptor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 |
package
com.example.demo.utils.security; import
javax.servlet.Filter; import
javax.servlet.FilterChain; import
javax.servlet.FilterConfig; import
javax.servlet.ServletException; import
javax.servlet.ServletRequest; import
javax.servlet.ServletResponse; import
org.springframework.beans.factory.annotation.Autowired; import
org.springframework.security.access.SecurityMetadataSource; import
org.springframework.security.access.intercept.AbstractSecurityInterceptor; import
org.springframework.security.access.intercept.InterceptorStatusToken; import
org.springframework.security.web.FilterInvocation; import
org.springframework.stereotype.Service; import
java.io.IOException; /**
* 許可權管理過濾器
*
* @Author: 我愛大金子
* @Description: 許可權管理過濾器
* @Date: Create in 17:16 2017/7/5
*/ @Service public
class
CustomFilterSecurityInterceptor
extends
AbstractSecurityInterceptor
implements
Filter {
@Autowired
private
CustomFilterInvocationSecurityMetadataSource customFilterInvocationSecurityMetadataSource;
// 許可權配置資源管理器
/**許可權管理決斷器*/
@Autowired
public
void
setMyAccessDecisionManager(CustomAccessDecisionManager customAccessDecisionManager) {
super
.setAccessDecisionManager(customAccessDecisionManager);
}
@Override
public
void
init(FilterConfig filterConfig)
throws
ServletException {
}
@Override
public
void
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws
IOException, ServletException {
FilterInvocation fi =
new
FilterInvocation(request, response, chain);
invoke(fi);
}
public
void
invoke(FilterInvocation fi)
throws
IOException, ServletException {
//fi裡面有一個被攔截的url
//裡面呼叫MyInvocationSecurityMetadataSource的getAttributes(Object object)這個方法獲取fi對應的所有許可權
//再呼叫MyAccessDecisionManager的decide方法來校驗使用者的許可權是否足夠
InterceptorStatusToken token =
super
.beforeInvocation(fi);
try
{
//執行下一個攔截器
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
}
finally
{
super
.afterInvocation(token,
null
);
}
}
@Override
public
void
destroy() {
}
@Override
public
Class<?> getSecureObjectClass() {
return
FilterInvocation.
class
;
}
@Override
public
SecurityMetadataSource obtainSecurityMetadataSource() {
return
this
.customFilterInvocationSecurityMetadataSource;
} } |
說明:
customFilterSecurityInterceptor:許可權管理過濾器
customAccessDecisionManager:許可權管理決斷器
customFilterInvocationSecurityMetadataSource:許可權配置資源管理器
其中過濾器在系統啟動時開始工作,並同時匯入許可權配置資源管理器和許可權管理決斷器,對使用者訪問的資源進行管理。許可權管理決斷器對使用者訪問的資源與使用者擁有的角色許可權進行對比,以此來判斷使用者是否對某個資源具有訪問許可權。
5.1、許可權管理過濾器
繼承與AbstractSecurityInterceptor,實時監控使用者的行為,防止使用者訪問未被授權的資源。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 |
package
com.example.demo.utils.security; import
javax.servlet.Filter; import
javax.servlet.FilterChain; import
javax.servlet.FilterConfig; import
javax.servlet.ServletException; import
javax.servlet.ServletRequest; import
javax.servlet.ServletResponse; import
org.slf4j.Logger; import
org.slf4j.LoggerFactory; import
org.springframework.beans.factory.annotation.Autowired; import
org.springframework.security.access.SecurityMetadataSource; import
org.springframework.security.access.intercept.AbstractSecurityInterceptor; import
org.springframework.security.access.intercept.InterceptorStatusToken; import
org.springframework.security.web.FilterInvocation; import
org.springframework.stereotype.Service; import
java.io.IOException; /**
* 許可權管理過濾器
*
* @Author: 我愛大金子
* @Description: 許可權管理過濾器
* @Date: Create in 17:16 2017/7/5
*/ @Service public
class
CustomFilterSecurityInterceptor
extends
AbstractSecurityInterceptor
implements
Filter {
Logger log = LoggerFactory.getLogger(CustomFilterSecurityInterceptor.
class
);
@Autowired
private
CustomFilterInvocationSecurityMetadataSource customFilterInvocationSecurityMetadataSource;
// 許可權配置資源管理器
/**許可權管理決斷器*/
@Autowired
public
void
setMyAccessDecisionManager(CustomAccessDecisionManager customAccessDecisionManager) {
super
.setAccessDecisionManager(customAccessDecisionManager);
}
@Override
public
void
init(FilterConfig filterConfig)
throws
ServletException {
}
@Override
public
void
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws
IOException, ServletException {
FilterInvocation fi =
new
FilterInvocation(request, response, chain);
log.info(
"【許可權管理過濾器】請求URL:"
+ fi.getRequestUrl());
invoke(fi);
}
public
void
invoke(FilterInvocation fi)
throws
IOException, ServletException {
//fi裡面有一個被攔截的url
//裡面呼叫CustomFilterInvocationSecurityMetadataSource的getAttributes(Object object)這個方法獲取fi對應的所有許可權
//再呼叫CustomAccessDecisionManager的decide方法來校驗使用者的許可權是否足夠
InterceptorStatusToken token =
super
.beforeInvocation(fi);
try
{
//執行下一個攔截器
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
}
catch
(Exception e) {
log.error(
"【許可權管理過濾器】【異常】"
+ e.getMessage(), e);
}
finally
{
super
.afterInvocation(token,
null
);
}
}
@Override
public
void
destroy() {
}
@Override
public
Class<?> getSecureObjectClass() {
return
FilterInvocation.
class
;
}
@Override
public
SecurityMetadataSource obtainSecurityMetadataSource() {
return
this
.customFilterInvocationSecurityMetadataSource;
} } |
5.2、許可權管理決斷器
許可權管理的關鍵部分就是決斷器,它實現了AccessDecisionManager,重寫了decide方法,使用自定義的決斷器,在使用者訪問受保護的資源時,決斷器判斷使用者擁有的角色中是否對改資源具有訪問許可權,如果沒有,則拒絕訪問
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
49
50
51
52
53
54
55
56
57
58
59
60
61 |
package
com.example.demo.utils.security; import
org.slf4j.Logger; import
org.slf4j.LoggerFactory; import
org.springframework.security.access.AccessDecisionManager; import
org.springframework.security.access.AccessDeniedException; import
org.springframework.security.access.ConfigAttribute; import
org.springframework.security.authentication.InsufficientAuthenticationException; import
org.springframework.security.core.Authentication; import
org.springframework.security.core.GrantedAuthority; import
org.springframework.stereotype.Service; import
java.util.Collection; import
java.util.Iterator; /**
* 許可權管理決斷器
*
* @Author: 我愛大金子
* @Description: 許可權管理決斷器
* @Date: Create in 17:15 2017/7/5
*/ @Service public
class
CustomAccessDecisionManager
implements
AccessDecisionManager {
Logger log = LoggerFactory.getLogger(CustomAccessDecisionManager.
class
);
// decide 方法是判定是否擁有許可權的決策方法,
//authentication 是釋CustomUserService中迴圈新增到 GrantedAuthority 物件中的許可權資訊集合.
//object 包含客戶端發起的請求的requset資訊,可轉換為 HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
//configAttributes 為MyInvocationSecurityMetadataSource的getAttributes(Object object)這個方法返回的結果,此方法是為了判定使用者請求的url 是否在許可權表中,如果在許可權表中,則返回給 decide 方法,用來判定使用者是否有此許可權。如果不在許可權表中則放行。
@Override
public
void
decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
throws
AccessDeniedException, InsufficientAuthenticationException {
if
(
null
== configAttributes || configAttributes.size() <=
0
) {
return
;
}
ConfigAttribute c;
String needRole;
for
(Iterator<ConfigAttribute> iter = configAttributes.iterator(); iter.hasNext(); ) {
c = iter.next();
needRole = c.getAttribute();
for
(GrantedAuthority ga : authentication.getAuthorities()) {
//authentication 為在註釋1 中迴圈新增到 GrantedAuthority 物件中的許可權資訊集合
if
(needRole.trim().equals(ga.getAuthority())) {
return
;
}
}
log.info(
"【許可權管理決斷器】需要role:"
+ needRole);
}
throw
new
AccessDeniedException(
"Access is denied"
);
}
@Override
public
boolean
supports(ConfigAttribute attribute) {
return
true
;
}
@Override
public
boolean
supports(Class<?> clazz) {
return
true
;
} } |
5.3、許可權配置資源管理器
許可權配置資源管理器實現了FilterInvocationSecurityMetadataSource, 在啟動時就去載入了所有的許可權列表,許可權配置資源管理器為決斷器實時提供支援,判斷使用者訪問的資源是否在受保護的範圍之內。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 |
package
com.example.demo.utils.security; import
com.example.demo.dao.SysPermissionDao; import
com.example.demo.pojo.SysPermission; import
org.springframework.beans.factory.annotation.Autowired; import
org.springframework.security.access.ConfigAttribute; import
org.springframework.security.access.SecurityConfig; import
org.springframework.security.web.FilterInvocation; import
org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import
org.springframework.security.web.util.matcher.AntPathRequestMatcher; import
org.springframework.stereotype.Service; import
javax.servlet.http.HttpServletRequest; import
java.util.*; /**
* 許可權配置資源管理器
*
* @Author: 我愛大金子
* @Description: 許可權配置資源管理器
* @Date: Create in 17:17 2017/7/5
*/ @Service public
class
CustomFilterInvocationSecurityMetadataSource
implements
FilterInvocationSecurityMetadataSource {
@Autowired
private
SysPermissionDao sysPermissionDao;
private
HashMap<String, Collection<ConfigAttribute>> map =
null
;
/**
* 載入許可權表中所有許可權
*/
public
void
loadResourceDefine(){
map =
new
HashMap<>();
Collection<ConfigAttribute> array;
ConfigAttribute cfg;
List<SysPermission> permissions = sysPermissionDao.findAll();
for
(SysPermission permission : permissions) {
array =
new
ArrayList<>();
cfg =
new
SecurityConfig(permission.getName());
//此處只新增了使用者的名字,其實還可以新增更多許可權的資訊,例如請求方法到ConfigAttribute的集合中去。此處新增的資訊將會作為MyAccessDecisionManager類的decide的第三個引數。
array.add(cfg);
//用許可權的getUrl() 作為map的key,用ConfigAttribute的集合作為 value,
map.put(permission.getUrl(), array);
}
}
//此方法是為了判定使用者請求的url 是否在許可權表中,如果在許可權表中,則返回給 decide 方法,用來判定使用者是否有此許可權。如果不在許可權表中則放行。
@Override
public
Collection<ConfigAttribute> getAttributes(Object object)
throws
IllegalArgumentException {
if
(map ==
null
) loadResourceDefine();
//object 中包含使用者請求的request 資訊
HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
AntPathRequestMatcher matcher;
String resUrl;
for
(Iterator<String> iter = map.keySet().iterator(); iter.hasNext(); ) {
resUrl = iter.next();
matcher =
new
AntPathRequestMatcher(resUrl);
if
(matcher.matches(request)) {
return
map.get(resUrl);
}
}
return
null
;
}
@Override
public
Collection<ConfigAttribute> getAllConfigAttributes() {
return
null
;
}
@Override
public
boolean
supports(Class<?> clazz) {
return
true
;
} } |
六、根據許可權設定連線
對於許可權管理,我們可能希望,在一個使用者訪問的介面中,不是等到使用者點選了超連結之後,才來判斷使用者有沒有這個許可權,而是按照使用者擁有的許可權來顯示超連結。這樣的設計對於使用者體驗來說,會更友好。
6.1、方法1:使用sec標籤(thymeleaf)
在html標籤中引入的Spring Security的標籤:
1 |
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4" |
sec:authentication="name":取當前登入使用者的使用者名稱
1 |
<
title
sec:authentication
=
"name"
></
title
> |
sec:authorize="hasRole('ROLE_ADMIN'):表示當前使用者是否擁有角色ROLE_ADMIN
1 |
<
li
sec:authorize
=
"hasRole('ROLE_ADMIN')"
><
a
th:href
=
"@{/admin}"
> admin </
a
></
li
> |
sec:authorize="hasAuthority('admin')":表示當前使用者是否擁有許可權admin
1 |
<
li
sec:authorize
=
"hasAuthority('admin')"
><
a
th:href
=
"@{/admin}"
> admin </
a
></
li
> |
6.2、方法二:程式碼
在控制層用程式碼獲取是否有許可權,然後將標識放入內容中,頁面獲取處理
七、其它程式碼
7.1、controller
IndexController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 |
package
com.example.demo.controller; import
com.example.demo.domain.Msg; import
org.springframework.stereotype.Controller; import
org.springframework.ui.Model; import
org.springframework.web.bind.annotation.RequestMapping; import
org.springframework.web.bind.annotation.ResponseBody; /**
* 描述
*
* @Author: 我愛大金子
* @Description: 描述
* @Date: Create in 15:25 2017/7/5
*/ @Controller public
class
IndexController {
/**系統首頁*/
@RequestMapping
(
"/"
)
public
String index(Model model){
Msg msg =
new
Msg(
"測試標題"
,
"測試內容"
,
"歡迎來到HOME頁面,您擁有index許可權"
);
model.addAttribute(
"msg"
, msg);
return
"home"
;
}
/**系統首頁2*/
@RequestMapping
(
"/index2"
)
public
String index2(Model model){
Msg msg =
new
Msg(
"測試標題2"
,
"測試內容2"
,
"歡迎來到HOME頁面,您擁有home許可權"
);
model.addAttribute(
"msg"
, msg);
return
"home"
;
}
@RequestMapping
(
"/admin"
)
@ResponseBody
public
String hello(){
return
"hello admin"
;
}
@RequestMapping
(
"/yk"
)
@ResponseBody
public
String hello2(){
return
"hello yk"
;
} } |
7.2、dao
SysUserDao.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 |
package
com.example.demo.dao; import
com.example.demo.pojo.SysUser; import
org.apache.ibatis.annotations.Mapper; /**
* 系統使用者dao
*
* @Author: 我愛大金子
* @Description: 系統使用者dao
* @Date: Create in 16:15 2017/7/5
*/ @Mapper public
interface
SysUserDao {
public
SysUser findByUserName(String username); } |
SysPermissionDao.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 |
package
com.example.demo.dao; import
com.example.demo.pojo.SysPermission; import
org.apache.ibatis.annotations.Mapper; import
java.util.List; /**
* 系統許可權dao
*
* @Author: 我愛大金子
* @Description: 描述
* @Date: Create in 17:05 2017/7/5
*/ @Mapper public
interface
SysPermissionDao {
List<SysPermission> findAll();
List<SysPermission> findByAdminUserId(Long userId); } |
7.3、domain
Msg.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 |
package
com.example.demo.domain; /**
* 描述
*
* @Author: 我愛大金子
* @Description: 描述
* @Date: Create in 16:14 2017/7/5
*/ public
class
Msg {
private
String title;
private
String content;
private
String etraInfo;
public
Msg(String title, String content, String etraInfo) {
super
();
this
.title = title;
this
.content = content;
this
.etraInfo = etraInfo;
}
public
String getTitle() {
return
title;
}
public
void
setTitle(String title) {
this
.title = title;
}
public
String getContent() {
return
content;
}
public
void
setContent(String content) {
this
.content = content;
}
public
String getEtraInfo() {
return
etraInfo;
}
public
void
setEtraInfo(String etraInfo) {
this
.etraInfo = etraInfo;
} } |
7.4、pojo
SysUser.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
49
50 |
package
com.example.demo.pojo; import
java.util.List; /**
* 系統使用者
*
* @Author: 我愛大金子
* @Description: 系統使用者
* @Date: Create in 16:12 2017/7/5
*/ public
class
SysUser {
private
Long id;
private
String username;
private
String password;
private
List<SysRole> roles;
public
Long getId() {
return
id;
}
public
void
setId(Long id) {
this
.id = id;
}
public
String getUsername() {
return
username;
}
public
void
setUsername(String username) {
this
.username = username;
}
public
String getPassword() {
return
password;
}
public
void
setPassword(String password) {
this
.password = password;
}
public
List<SysRole> getRoles() {
return
roles;
}
public
void
setRoles(List<SysRole> roles) {
this
.roles = roles;
} } |
SysRole.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 |
package
com.example.demo.pojo; /**
* 系統角色
*
* @Author: 我愛大金子
* @Description: 系統角色
* @Date: Create in 16:13 2017/7/5
*/ public
class
SysRole {
private
Long id;
private
String name;
public
Long getId() {
return
id;
}
public
void
setId(Long id) {
this
.id = id;
}
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
} } |
SysPermission.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 |
package
com.example.demo.pojo; /**
* 系統許可權
*
* @Author: 我愛大金子
* @Description: 系統許可權
* @Date: Create in 17:04 2017/7/5
*/ public
class
SysPermission {
private
Long id;
//許可權名稱
private
String name;
//許可權描述
private
String descritpion;
//授權連結
private
String url;
//父節點id
private
int
pid;
public
Long getId() {
return
id;
}
public
void
setId(Long id) {
this
.id = id;
}
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
String getDescritpion() {
return
descritpion;
}
public
void
setDescritpion(String descritpion) {
this
.descritpion = descritpion;
}
public
String getUrl() {
return
url;
}
public
void
setUrl(String url) {
this
.url = url;
}
public
int
getPid() {
return
pid;
}
public
void
setPid(
int
pid) {
this
.pid = pid;
} } |
7.5、mapperXX.xml
SysUserDao.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 |
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
" <
mapper
namespace
=
"com.example.demo.dao.SysUserDao"
>
<
resultMap
id
=
"userMap"
type
=
"SysUser"
>
<
id
property
=
"id"
column
=
"ID"
/>
<
result
property
=
"username"
column
=
"username"
/>
<
result
property
=
"password"
column
=
"PASSWORD"
/>
<
collection
property
=
"roles"
ofType
=
"SysRole"
>
<
result
column
=
"name"
property
=
"name"
/>
</
collection
>
</
resultMap
>
<
select
id
=
"findByUserName"
parameterType
=
"String"
resultMap
=
"userMap"
>
select u.*
,r.name
from sys_user u
LEFT JOIN sys_user_role sru on u.id= sru.sys_user_id
LEFT JOIN sys_role r on sru.sys_role_id=r.id
where username= #{username}
</
select
> </
mapper
> |
SysPermissionDao.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 |
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
" <
mapper
namespace
=
"com.example.demo.dao.SysPermissionDao"
>
<
select
id
=
"findAll"
resultType
=
"SysPermission"
>
SELECT * from sys_permission ;
</
select
>
<
select
id
=
"findByAdminUserId"
parameterType
=
"java.lang.Long"
resultType
=
"SysPermission"
>
SELECT
p.*
FROM sys_user u
LEFT JOIN sys_user_role sru ON u.id= sru.sys_user_id
LEFT JOIN sys_role r ON sru.sys_role_id=r.id
LEFT JOIN sys_role_permission spr ON spr.sys_role_id=r.id
LEFT JOIN Sys_permission p ON p.id =spr.sys_permission_id
WHERE u.id=#{userId}
</
select
> </
mapper
> |
7.6、html
login.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
49
50
51
52
53 |
<!DOCTYPE html> <
html
xmlns:th
=
"
> <
head
>
<
meta
content
=
"text/html;charset=UTF-8"
/>
<
title
>登入頁面</
title
>
<
link
rel
=
"stylesheet"
th:href
=
"@{css/bootstrap.min.css}"
/>
<
style
type
=
"text/css"
>
body {
padding-top: 50px;
}
.starter-template {
padding: 40px 15px;
text-align: center;
}
</
style
> </
head
> <
body
> <
nav
class
=
"navbar navbar-inverse navbar-fixed-top"
>
<
div
class
=
"container"
>
<
div
class
=
"navbar-header"
>
<
a
class
=
"navbar-brand"
href
=
"#"
>Spring Security演示</
a
>
</
div
>
<
div
id
=
"navbar"
class
=
"collapse navbar-collapse"
>
<
ul
class
=
"nav navbar-nav"
>
<
li
><
a
th:href
=
"@{/}"
> 首頁 </
a
></
li
>
</
ul
>
</
div
>
<!--/.nav-collapse -->
</
div
> </
nav
> <
div
class
=
"container"
>
<
div
class
=
"starter-template"
>
<
p
th:if
=
"${param.logout}"
class
=
"bg-warning"
>已成功登出</
p
>
<!-- 1 -->
<
p
th:if
=
"${param.illegal}"
class
=
"bg-warning"
>無權訪問,請切換賬號登入</
p
>
<!-- 1 -->
<
p
th:if
=
"${param.error}"
class
=
"bg-danger"
>使用者名稱或密碼錯誤</
p
>
<!-- 2 -->
<
h2
>使用賬號密碼登入</
h2
>
<
form
name
=
"form"
th:action
=
"@{/login}"
action
=
"/login"
method
=
"POST"
>
<!-- 3 -->
<
div
class
=
"form-group"
>
<
label
for
=
"username"
>賬號</
label
>
<
input
type
=
"text"
class
=
"form-control"
name
=
"username"
value
=
""
placeholder
=
"賬號"
/>
</
div
>
<
div
class
=
"form-group"
>
<
label
for
=
"password"
>密碼</
label
>
<
input
type
=
"password"
class
=
"form-control"
name
=
"password"
placeholder
=
"密碼"
/>
</
div
>
<
input
type
=
"submit"
id
=
"login"
value
=
"Login"
class
=
"btn btn-primary"
/>
</
form
>
</
div
> </
div
> </
body
> </
html
> |
home.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
49
50
51
52
53 |
<!DOCTYPE html> <
html
xmlns:th
=
"
xmlns:sec
=
"http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"
> <
head
>
<
meta
content
=
"text/html;charset=UTF-8"
/>
<
title
sec:authentication
=
"name"
></
title
>
<
link
rel
=
"stylesheet"
th:href
=
"@{css/bootstrap.min.css}"
/>
<
style
type
=
"text/css"
>
body {
padding-top: 50px;
}
.starter-template {
padding: 40px 15px;
text-align: center;
}
</
style
> </
head
> <
body
> <
nav
class
=
"navbar navbar-inverse navbar-fixed-top"
>
<
div
class
=
"container"
>
<
div
class
=
"navbar-header"
>
<
a
class
=
"navbar-brand"
href
=
"#"
>Spring Security演示</
a
>
</
div
>
<
div
id
=
"navbar"
class
=
"collapse navbar-collapse"
>
<
ul
class
=
"nav navbar-nav"
>
<
li
><
a
th:href
=
"@{/}"
> 首頁 </
a
></
li
>
<
li
sec:authorize
=
"hasAuthority('admin')"
><
a
th:href
=
"@{/admin}"
> admin </
a
></
li
>
</
ul
>
</
div
>
<!--/.nav-collapse -->
</
div
> </
nav
> <
div
class
=
"container"
>
<
div
class
=
"starter-template"
>
<
h1
th:text
=
"${msg.title}"
></
h1
>
<
p
class
=
"bg-primary"
th:text
=
"${msg.content}"
></
p
>
<
div
>
<
p
class
=
"bg-info"
th:text
=
"${msg.etraInfo}"
></
p
>
</
div
>
<
form
th:action
=
"@{/logout}"
method
=
"post"
>
<
input
type
=
"submit"
class
=
"btn btn-primary"
value
=
"登出"
/>
</
form
>
</
div
> </
div
> </
body
> </
html
> |
轉載於:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69952307/viewspace-2674986/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- java b2b2c電子商務 springcloud分散式微服務-Session共享JavaSpringGCCloud分散式微服務Session
- SpringCloud分散式微服務b2b2c電子商務-Gateway的基本入門SpringGCCloud分散式微服務Gateway
- SpringCloud分散式微服務b2b2c電子商務分散式微服務-docker-feign-hystrix(七)SpringGCCloud分散式微服務Docker
- Springcloud分散式微服務b2b2c電子商務一整合Hystrix(二)SpringGCCloud分散式微服務
- JAVA spring cloud boot b2b2c電子商務分散式微服務JavaSpringCloudboot分散式微服務
- SpringCloud分散式微服務b2b2c電子商務(五)springboot整合 beatlsqlGCCloud分散式微服務Spring BootTLSSQL
- SpringCloud分散式微服務b2b2c電子商務docker-feign配置(六)SpringGCCloud分散式微服務Docker
- SpringCloud分散式微服務b2b2c電子商務-hystrix引數詳解(十)SpringGCCloud分散式微服務
- SpringCloud分散式微服務b2b2c電子商務(十三)Springboot整合RabbitMQGCCloud分散式微服務Spring BootMQ
- SpringCloud分散式微服務b2b2c電子商務(一)元件和概念介紹SpringGCCloud分散式微服務元件
- SpringCloud分散式微服務b2b2c電子商務-SpringBoot 整合JPA(四)GCCloud分散式微服務Spring Boot
- (十四)JAVA springboot微服務b2b2c電子商務系統- Spring Cloud構建分散式電子商務平臺JavaSpring Boot微服務Cloud分散式
- SpringCloud分散式微服務b2b2c電子商務-定時任務(Scheduling Tasks)SpringGCCloud分散式微服務
- Java b2b2c電子商務 SpringCloud分散式微服務-config的簡單配置shh方式JavaSpringGCCloud分散式微服務
- SpringCloud分散式微服務b2b2c電子商務(三)註冊中心叢集篇SpringGCCloud分散式微服務
- SpringCloud分散式微服務b2b2c電子商務-Spring Boot配置檔案詳解GCCloud分散式微服務Spring Boot
- SpringCloud分散式微服務b2b2c電子商務docker-feign-hystrix-ribbon(八)SpringGCCloud分散式微服務Docker
- SpringCloud分散式微服務b2b2c電子商務-docker部署spring cloud專案(十一)SpringGCCloud分散式微服務Docker
- Springcloud分散式微服務b2b2c電子商務一Spring Cloud常見問題(一)SpringGCCloud分散式微服務
- SpringCloud分散式微服務b2b2c電子商務(二)Eureka(服務註冊和服務發現基礎篇)SpringGCCloud分散式微服務
- 微服務、分散式、雲架構構建電子商務平臺微服務分散式架構
- SpringCloud分散式微服務b2b2c電子商務-Spring Cloud自定義引導屬性源SpringGCCloud分散式微服務
- java B2B2C Springcloud電子商務平臺原始碼-Ribbon 基本使用JavaSpringGCCloud原始碼
- 分散式微服務雲架構電子商務平臺分散式微服務架構
- 分散式微服務雲架構構建電子商務分散式微服務架構
- java B2B2C Springcloud電子商務平臺原始碼JavaSpringGCCloud原始碼
- SpringCloud分散式微服務b2b2c電子商務(十二)在springboot中用redis實現訊息佇列GCCloud分散式微服務Spring BootRedis佇列
- 關於SpringCloud微服務雲架構構建B2B2C電子商務平臺之-(SpringGCCloud微服務架構
- java版電子商務spring cloud分散式微服務-大話Spring CloudJavaSpringCloud分散式微服務
- java版 電子商務Springcloud分散式微服務多使用者商城系統-Springboot專案打包JavaGCCloud分散式微服務Spring Boot
- 電子商務Java微服務 SpringBoot整合SpringSecurityJava微服務Spring BootGse
- 構建分散式微服務雲架構電子商務平臺分散式微服務架構
- 分散式微服務雲架構構建電子商務平臺分散式微服務架構
- JAVA商城 B2B2C商城系統 小程式 電子商務 springcloud商城JavaSpringGCCloud
- JAVA springboot微服務b2b2c電子商務系統-(七)高可用的分散式配置中心(Spring Cloud Config)JavaSpring Boot微服務分散式Cloud
- SpringCloud微服務雲架構構建B2B2C電子商務平臺分析之-服務消費(Ribbon)SpringGCCloud微服務架構
- java B2B2C 仿淘寶電子商城系統-Spring Cloud構建分散式電子商務平臺JavaSpringCloud分散式
- 微服務雲架構電子商務平臺微服務架構