赞
踩
Spring Security 是一个功能强大且高度可定制的身份证认证和访问控制框架。其最重要的两部分是认证(Authentication)和授权(Authorization)。
本实例使用框架:
我们引入spring-boot-starter-security
包,同时为完成实例引入了其他的包,这里不多做介绍
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> </dependencies>
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot-security?charset=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: root
jpa:
show-sql: true
hibernate:
ddl-auto: update
我们创建一个Security的配置类,并继承WebSecurityConfigurerAdapter
类,加上@EnableWebSecurity
注解,表示启用Security,下面看详细代码
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Resource private UserDao userDao; @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/css/**", "/", "/index", "/loginPage").permitAll() // 无需认证 .anyRequest().authenticated() // 其他请求都需要认证 ; http.formLogin() // 开启登录,如果没有权限,就会跳转到登录页 .loginPage("/loginPage") // 自定义登录页,默认/login(get请求) .loginProcessingUrl("/login") // 登录处理地址,默认/login(post请求) .usernameParameter("inputEmail") // 自定义username属性名,默认username .passwordParameter("inputPassword") // 自定义password属性名,默认password ; http.rememberMe() // 开启记住我 .rememberMeParameter("rememberMe") // 自定义rememberMe属性名 ; http.logout() // 开启注销 .logoutUrl("/logout") // 注销处理路径,默认/logout .logoutSuccessUrl("/") // 注销成功后跳转路径 ; http.csrf().disable(); // 禁止csrf } @Bean public UserDetailsService userDetailsService() { return username -> { xyz.zyl2020.security.entity.User user = userDao.findByUsernameOrEmail(username, username); if (user == null) { throw new UsernameNotFoundException("账号或密码错误!"); } String[] roleCodeArray = user.getRoles().stream().map(Role::getCode).toArray(String[]::new); return User.withUsername(user.getUsername()) .password(user.getPassword()) .roles(roleCodeArray) .build(); }; } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
configure(HttpSecurity http)
方法,用于配置http请求认证
http.authorizeRequests()
为请求授权,可以定义哪些资源无需认证,哪些资源需要认证http.formLogin()
开启form表单登录,可自定义登录页,登录请求处理,还有账号、密码使用的参数等http.rememberMe()
开启记住我功能http.logout()
开户注销功能,并可自定义注解成功跳转路径http.csrf()
CSRF防护,默认是开启的。若开启,则在表单中增加 input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
userDetailsService()
配置鉴权,用户验证用户及权限。此时可以从数据库中查出用户及权限信息,构建UserDetailsService
类并返回,进行下一步验证,由Spring Security自行验证passwordEncoder()
配置密码编码格式,不启用会报下面异常,这里我们使用BCrypt
。在用户注册时,密码使用相同的编码格式存库,BCrypt.hashpw("password", BCrypt.gensalt())
2020-08-24 22:03:20.014 ERROR 4692 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
......
@Controller public class RouteController { @RequestMapping({"/", "/index"}) public String index() { return "index"; } @GetMapping("/loginPage") public String loginPage() { return "login"; } @GetMapping("/currentUser") public String getUsername() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); Object principal = authentication.getPrincipal(); if (principal == null) { return null; } UserDetails userDetails = (UserDetails) principal; return userDetails.getUsername(); } }
index()
指向主页,对应resources/templates/index.html
loginPage()
指向登录页,对应resources/templates/login.html
Service层、Dao层、和实体类查阅下面的【完整代码】吧,另外用户、角色、及其关系的初始化,在test代码中
<form class="form-signin" action="/login" method="post">
<h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
<label for="inputEmail" class="sr-only">Email address</label>
<input type="email" id="inputEmail" name="inputEmail" class="form-control" placeholder="Email address" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" id="inputPassword" name="inputPassword" class="form-control" placeholder="Password" required>
<div class="checkbox mb-3">
<label>
<input type="checkbox" name="rememberMe"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2017-2020</p>
</form>
action="/login"
对应着后台配置loginProcessingUrl("/login")
,这两个路径要一致name
名,与后台配置要保持一致做好以前配置,提交表单后会将用户名、密码、记住我信息提交致后台进行认证授权
thymeleaf与Security集成,主要使用引入的thymeleaf-extras-springsecurity5
包
<!doctype html> <html lang="en" xmlns:sec="http://www.thymeleaf.org/extras/spring-security"> <head> // 代码省略... </head> <body> <div class="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom shadow-sm"> <h5 class="my-0 mr-md-auto font-weight-normal">Welcome!</h5> <nav class="my-2 my-md-0 mr-md-3"> <div sec:authorize="!isAuthenticated()"> <a class="btn btn-outline-primary" href="/loginPage">Login</a> </div> <div sec:authorize="isAuthenticated()"> <span sec:authentication="name"></span> <a class="btn btn-outline-primary" href="/logout">Logout</a> </div> </nav> </div> <div class="pricing-header px-3 py-3 pt-md-5 pb-md-4 mx-auto text-center"> <h1 class="display-4">Pricing</h1> <p class="lead">Quickly build an effective pricing table for your potential customers with this Bootstrap example. It’s built with default Bootstrap components and utilities with little customization.</p> </div> <div class="container"> <div class="card-deck mb-3 text-center"> <div class="card mb-4 shadow-sm" sec:authorize="hasAnyRole('FREE')"> <div class="card-header"> <h4 class="my-0 font-weight-normal">Free</h4> </div> <div class="card-body"> <h1 class="card-title pricing-card-title">$0 <small class="text-muted">/ mo</small></h1> <ul class="list-unstyled mt-3 mb-4"> <li>10 users included</li> <li>2 GB of storage</li> <li>Email support</li> <li>Help center access</li> </ul> <a class="btn btn-lg btn-block btn-primary" href="#">Get started</a> </div> </div> <div class="card mb-4 shadow-sm" sec:authorize="hasAnyRole('PRO')"> <div class="card-header"> <h4 class="my-0 font-weight-normal">Pro</h4> </div> <div class="card-body"> <h1 class="card-title pricing-card-title">$15 <small class="text-muted">/ mo</small></h1> <ul class="list-unstyled mt-3 mb-4"> <li>20 users included</li> <li>10 GB of storage</li> <li>Priority email support</li> <li>Help center access</li> </ul> <a class="btn btn-lg btn-block btn-primary">Get started</a> </div> </div> <div class="card mb-4 shadow-sm" sec:authorize="hasAnyRole('ENT')"> <div class="card-header"> <h4 class="my-0 font-weight-normal">Enterprise</h4> </div> <div class="card-body"> <h1 class="card-title pricing-card-title">$29 <small class="text-muted">/ mo</small></h1> <ul class="list-unstyled mt-3 mb-4"> <li>30 users included</li> <li>15 GB of storage</li> <li>Phone and email support</li> <li>Help center access</li> </ul> <a class="btn btn-lg btn-block btn-primary">Get started</a> </div> </div> </div> </div> </body> </html>
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
命名空间,便可在html中使用security功能了sec:authorize="isAuthenticated()"
标签表示已验证通过,即登录成功sec:authentication="name"
获取当前用户名sec:authorize="hasAnyRole('FREE')"
表示拥有指定角色方可显示内容sec:authorize="hasAnyAuthority('user:add')"
表示拥有指定权限方可显示内容更多功能请参照官网
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。