想关依赖,采用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将自动完成注销操作