spring security實現登入驗證以及根據使用者身份跳轉不同頁面
阿新 • • 發佈:2018-11-07
想關依賴,採用session加redis儲存使用者資訊
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>com.ibeetl</groupId> <artifactId>beetl-framework-starter</artifactId> <version>1.1.56.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.persistence/javax.persistence-api --> <dependency> <groupId>javax.persistence</groupId> <artifactId>javax.persistence-api</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--session start--> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> <version>5.0.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.0.8.RELEASE</version> </dependency> <!--end--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>mockwebserver</artifactId> <version>3.11.0</version> </dependency> <dependency><!--自動生成getter,setter--> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.15</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-base</artifactId> <version>3.0.3</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-web</artifactId> <version>3.0.3</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-annotation</artifactId> <version>3.0.3</version> </dependency> <!--end-->
登入處理類將使用者資訊存入spring security(此類是通過username獲取使用者的合法使用者名稱,密碼,許可權,並建立合法使用者,
spring security將自動與使用者輸入的進行匹配)
@Service @Transactional public class UserDetailsServiceIm implements UserDetailsService { private member memb,memRoles; @Autowired private MemberEn mem; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { System.out.println("Running:\tUserDetails loadUserByUsername"); memb=mem.getMember(username); if (memb == null){ throw new UsernameNotFoundException("user not found");//丟擲異常,會根據配置跳到登入失敗頁面 } memRoles=mem.getMemRole(memb.getId());//根據查詢的id查詢角色與urls User.UserBuilder builder; if(memb!=null) { String[] roles=memRoles.getRoleName().split(","); builder=org.springframework.security.core.userdetails.User.withUsername(username); builder.password(new BCryptPasswordEncoder().encode(memb.getPasswd())); for (String role:roles ) { System.out.println(role); } builder.roles(roles); } else { throw new UsernameNotFoundException("member not found"); } return builder.build(); }
webconfig類。
@Configuration @EnableWebSecurity public class WebSecConfig extends WebSecurityConfigurerAdapter { @Bean public UserDetailsService userDetailsService(){ return new UserDetailsServiceIm(); } @Bean public BCryptPasswordEncoder passwordEncoder(){//資料庫密碼密碼加密 return new BCryptPasswordEncoder(){ @Override public String encode(CharSequence rawPassword) { // return MD5Utiles.encode(String.valueOf(rawPassword)); return super.encode(rawPassword); } @Override public boolean matches(CharSequence rawPassword, String encodedPassword) { // return encodedPassword.equals(MD5Utiles.encode(String.valueOf(rawPassword))); return super.matches(rawPassword, encodedPassword); } }; } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder()); } @Autowired MemberEn memberEn; @Override protected void configure(HttpSecurity http) throws Exception { Map<String,String[]> map=memberEn.getRoleUrl(); if (map!=null) { Iterator<?> iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry) iterator.next(); String url = (String) entry.getKey(); String[] roles = (String[]) entry.getValue(); if (roles.length > 0) { http.authorizeRequests().antMatchers(url).hasAnyRole(roles).anyRequest().authenticated(); } } } else { System.out.println("未查詢到使用者型別對應url的對映"); } http.authorizeRequests().anyRequest().authenticated() .and().formLogin().loginPage("/login").defaultSuccessUrl("/mem/index.html").failureUrl("/login/error").permitAll() .passwordParameter("password").usernameParameter("username") .and().logout().logoutUrl("/test/api/exit").logoutSuccessUrl("/login") .invalidateHttpSession(true).permitAll() .and().csrf().disable();//關閉CSRF保護 } @Override//web security忽略以下url public void configure(WebSecurity web) throws Exception { super.configure(web); web.ignoring().antMatchers( "/**/*.js","/**/*.css","/**/*.js", "/**/*.jpg","/**/*.png","/**/*.jpeg","/test/*" ); }
編寫相應的介面處理登入狀態跳轉(登入表單的action屬性設成/login,不然無法攔截登入資訊,這是spring security預設的,也可以進行修改)
@RequestMapping("/login")//內部使用者登入攔截,spring security登入控制預設攔截/login路徑,表單post為/login
public ModelAndView login(){
return new ModelAndView("/login.html");
}
@RequestMapping(value = "/login/error")
public @ResponseBody String doLoginError(){
return "false";
}
控制層:攔截使用者請求,並根據使用者身份跳轉
@Controller
@RequestMapping("/mem")
public class MemEnContr {
private ModelAndView modelAndView;
@RequestMapping("/index.html")//根據角色跳轉,這裡對應的是webconfig類中設定好的登入成功url跳轉
public ModelAndView doLogin(){
switch (PermissionServer.getAuthe()){
case "[ROLE_推薦單位]":modelAndView = new ModelAndView("redirect:/pro/hom/index.html");
break;
case "[ROLE_計劃科]":modelAndView = new ModelAndView("redirect:/pro/hom/index.html");
break;
case "[ROLE_admin]":modelAndView = new ModelAndView("redirect:/pro/hom/index.html");
break;
case "[ROLE_其他科室]":modelAndView = new ModelAndView("redirect:/pro/hom/index.html");
break;
case "[ROLE_受理中心]":modelAndView = new ModelAndView("redirect:/pro/hom/index.html");
default:
modelAndView = new ModelAndView("redirect:/login");//未登入或許可權不夠
break;
}
return modelAndView;
}
注意登入表單post的action屬性要設定為與websecconfig類中一致才能被攔截,還需設定將驗證成功的跳轉url指向控制層相應的@RequestMapping
.and().formLogin().loginPage("/login").permitAll().defaultSuccessUr
使用者登出登入以及登出後跳轉到登入頁面:
.and().logout().logoutUrl("/mem/api/exit").logoutSuccessUrl("/login").permitAll().and().csrf().disable();//關閉CSRF保護
這裡需要說明的是我們只需將頁面的登出按鈕的src="./mem/api/exit"即可,不需要再控制層實現/mem/api/exit的相關方法,spring將自動完成登出操作