最終效果
成都創(chuàng)新互聯(lián)公司于2013年成立,先為白云等服務(wù)建站,白云等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為白云企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。
1、實現(xiàn)頁面訪問權(quán)限限制
2、用戶角色區(qū)分,并按照角色區(qū)分頁面權(quán)限
3、實現(xiàn)在數(shù)據(jù)庫中存儲用戶信息以及角色信息
4、自定義驗證代碼
效果如下:
1、免驗證頁面
2、登陸頁面
在用戶未登錄時,訪問任意有權(quán)限要求的頁面都會自動跳轉(zhuǎn)到登陸頁面。
3、需登陸才能查看的頁面
用戶登陸后,可以正常訪問頁面資源,同時可以正確顯示用戶登錄名:
4、用戶有角色區(qū)分,可以指定部分頁面只允許有相應(yīng)用戶角色的人使用
4.1、只有ADMIN覺得用戶才能查看的頁面(權(quán)限不足)
4.2、只有ADMIN覺得用戶才能查看的頁面(權(quán)限滿足)
以下具體說明實現(xiàn)步驟。
代碼實現(xiàn)
MAVEN引入依賴
在pom.xml中引入spring security依賴
org.springframework.boot spring-boot-starter-security
配置Spring Security
在Spring中,配置和使用Spring Security,在不需要修改太多流程細(xì)節(jié)的情況下僅需聲明好攔截規(guī)則,同時自定義驗證過程中的主要實現(xiàn)接口(用戶信息UserDetails,用戶信息獲取服務(wù)UserDetailsService,驗證工具AuthenticationProvider)即可。其余的流程將由Spring自動接管,非常方便。
啟動配置
在項目包下添加WebSecurityConfigurerAdapter
的具體實現(xiàn)類,實現(xiàn)Spring Security的啟動配置
代碼如下:
@Configurable @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true)//允許進(jìn)入頁面方法前檢驗 public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private MyAuthenticationProvider provider;//自定義驗證 @Autowired private UserDetailsService userDetailsService;//自定義用戶服務(wù) @Autowired public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception{ } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers(StaticParams.PATHREGX.NOAUTH, StaticParams.PATHREGX.CSS,StaticParams.PATHREGX.JS,StaticParams.PATHREGX.IMG).permitAll()//無需訪問權(quán)限 .antMatchers(StaticParams.PATHREGX.AUTHADMIN).hasAuthority(StaticParams.USERROLE.ROLE_ADMIN)//admin角色訪問權(quán)限 .antMatchers(StaticParams.PATHREGX.AUTHUSER).hasAuthority(StaticParams.USERROLE.ROLE_USER)//user角色訪問權(quán)限 .anyRequest()//all others request authentication .authenticated() .and() .formLogin().loginPage("/login").permitAll() .and() .logout().permitAll(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { //將驗證過程交給自定義驗證工具 auth.authenticationProvider(provider); }
URL攔截配置
URL攔截配置可以在上一小節(jié)的WebSecurityConfig 中配置,但是此方法適用于大方向上的配置,具體的特殊路徑也可以在@Controller的注解中具體配置。
如下:
@ResponseBody @PreAuthorize("hasAuthority('"+StaticParams.USERROLE.ROLE_ADMIN+"')")//這里可以指定特定角色的用戶訪問權(quán)限 @RequestMapping(value = "adminrequire", method = RequestMethod.GET) public String adminrequire(){ return "HELLO from web but you should be admin"; }
用戶、角色表
在本文例子中用戶和角色可以有一對多的關(guān)系因此可以將用戶和角色分成兩張表。有些例子將用戶和權(quán)限寫在同一張表上也是可以的。
/*用戶表*/ @Entity @Table(name = "user") public class SystemUser { @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String userName; private String password; public SystemUser(){} public SystemUser(SystemUser user){ this.userName = user.getUserName(); this.password = user.getPassword(); this.id = user.getId(); } 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; } } /*角色表*/ @Entity @Table(name = "user_role") public class UserRole { @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String role; private Long userId; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getRole() { return role; } public void setRole(String role) { this.role = role; } public Long getUserId() { return userId; } public void setUserId(Long userId) { this.userId = userId; } }
自定義驗證
在Spring Boot的Spring Security的教程中默認(rèn)的用戶名、密碼、權(quán)限是在代碼中指定的
@Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); }
這顯然是不符合應(yīng)用需求的,所以我們需要提供自定義的AuthenticationProvider,并在上邊代碼中替換即可。在此之前,我們應(yīng)該重寫獲取用戶User和權(quán)限的方法。通過查詢相關(guān)資料和API,方法提供如下:
自定義UserDetails
UserDetails代表了Spring Security的用戶認(rèn)證實體,帶有用戶名、密碼、權(quán)限列表、過期特性等性質(zhì),可以自己聲明類實現(xiàn)UserDetails接口,如果不想自己聲明,也可以用SpringSecurity的默認(rèn)實現(xiàn)org.springframework.security.core.userdetails.User 本文例子中采用自定義類:
public class MyUserDetails extends SystemUser implements UserDetails{ private Listroles; public MyUserDetails(SystemUser user, List roles){ super(user); this.roles = roles; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { if(roles == null || roles.size() <1){ return AuthorityUtils.commaSeparatedStringToAuthorityList(""); } StringBuilder commaBuilder = new StringBuilder(); for(UserRole role : roles){ commaBuilder.append(role.getRole()).append(","); } String authorities = commaBuilder.substring(0,commaBuilder.length()-1); return AuthorityUtils.commaSeparatedStringToAuthorityList(authorities); } @Override public String getPassword() { return super.getPassword(); } @Override public String getUsername() { return super.getUserName(); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }
自定義UserDetailsService
UserDetailsService提供了獲取UserDetails的方式,只要實現(xiàn)UserDetailsService接口即可,最終生成用戶和權(quán)限共同組成的UserDetails,在這里就可以實現(xiàn)從自定義的數(shù)據(jù)源中獲取用戶信息了:
@Service("MyUserDetailsImpl") public class MyUserDetailsService implements UserDetailsService { @Resource(name = "SystemUserServiceImpl") private SystemUserService systemUserService; @Resource(name = "UserRoleServiceImpl") private UserRoleService userRoleService; @Override public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException { SystemUser user; try { user = systemUserService.findByName(userName); } catch (Exception e) { throw new UsernameNotFoundException("user select fail"); } if(user == null){ throw new UsernameNotFoundException("no user found"); } else { try { Listroles = userRoleService.getRoleByUser(user); return new MyUserDetails(user, roles); } catch (Exception e) { throw new UsernameNotFoundException("user role select fail"); } } } }
自定義AuthenticationProvider
AuthenticationProvider 提供用戶UserDetails的具體驗證方式,在這里可以自定義用戶密碼的加密、驗證方式等等。因為博文主要講的是如何引入Spring Security和如何自定義驗證代碼,所以這里為了簡便,我直接采用明文比較方式:
@Component public class MyAuthenticationProvider implements AuthenticationProvider { @Autowired private MyUserDetailsService userService; /** * 自定義驗證方式 */ @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = authentication.getName(); String password = (String) authentication.getCredentials(); MyUserDetails user = (MyUserDetails) userService.loadUserByUsername(username); if(user == null){ throw new BadCredentialsException("Username not found."); } //加密過程在這里體現(xiàn) if (!password.equals(user.getPassword())) { throw new BadCredentialsException("Wrong password."); } Collection<? extends GrantedAuthority> authorities = user.getAuthorities(); return new UsernamePasswordAuthenticationToken(user, password, authorities); } @Override public boolean supports(Class<?> arg0) { return true; } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。