http://localhost:1888/api/blade-auth/oauth/captcha
2. 用户登录
使用spring security oauth2实现,登录接口
系统集成了redis缓存
使用缓存:
@Cacheable(cacheNames = {DICT_CACHE},key="'sys:ld:dic:' + #code")
清除缓存
@CacheEvict(cacheNames = {DICT_CACHE}, allEntries = true)
http://localhost:1888/api/blade-system/dict/child-list?current=1&size=10&parentId=1123598814738675204
会查询缓存(比如blade:dict::dict: id:1123598814738675204),id表示是当前字典表的父节点,存储的是Dict对象
错误日志
接口日志
@ApiLog("")
通用日志
引用BladeLogger
web动态配置角色
@PreAuth(“hasPermission(‘permission_test’)”)
根据接口上的permission和roleid去查询,放入缓存
@PreAuth(“permissionAll()”)
根据配置的权限路径和访问的接口路径比对,如果包含此接口路径,表示有权限。
还有其他的一些权限判断,在AuthFun里面找函数名
@Configuration
@AllArgsConstructor
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Bean
@Override
@SneakyThrows
public AuthenticationManager authenticationManagerBean() {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return BladePasswordEncoderFactories.createDelegatingPasswordEncoder();
}
@Override
public void configure(WebSecurity web) {
//Ignore, public
web.ignoring().antMatchers("/static/**");
}
@Override
@SneakyThrows
protected void configure(HttpSecurity http) {
http.authorizeRequests()
// permitAll() 的URL路径属于公开访问,不需要权限
.antMatchers("/oauth2.0/show*").permitAll()
.antMatchers(HttpMethod.GET, "/oauth2.0/show*").anonymous()
.anyRequest().authenticated();
http
.formLogin()
.loginPage("/oauth2.0/show")
.loginProcessingUrl("/signin")
.failureUrl("/oauth2.0/show?error=1")
.usernameParameter("username")
.passwordParameter("password")
.and()
.logout()
.logoutUrl("/signout")
.deleteCookies("JSESSIONID")
.logoutSuccessUrl("/")
.and()
.exceptionHandling();
http.httpBasic().disable();
}
}
@Controller
public class OauthController {
@GetMapping(value = {"/oauth2.0/show"})
public String login(Model model, HttpServletRequest request) {
CsrfToken csrf = (CsrfToken) request.getAttribute("_csrf");
model.addAttribute("csrf", csrf.getToken());
return "login";
}
@RequestMapping("/custom/confirm_access")
public ModelAndView getAccessConfirmation(@RequestParam Map<String, Object> map, HttpServletRequest request) throws Exception {
ModelAndView view = new ModelAndView();
view.setViewName("grant");
view.addObject("clientId",map.get("client_id"));
return view;
}
}
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>第三方登录title>
head>
<style>
.login-container {
margin: 50px;
width: 100%;
}
.form-container {
margin: 0px auto;
width: 50%;
text-align: center;
box-shadow: 1px 1px 10px #888888;
height: 300px;
padding: 5px;
}
input {
margin-top: 10px;
width: 350px;
height: 30px;
border-radius: 3px;
border: 1px #E9686B solid;
padding-left: 2px;
}
.btn {
width: 350px;
height: 35px;
line-height: 35px;
cursor: pointer;
margin-top: 20px;
border-radius: 3px;
background-color: #E9686B;
color: white;
border: none;
font-size: 15px;
}
.title {
margin-top: 5px;
font-size: 18px;
color: #E9686B;
}
style>
<body>
<div class="login-container">
<div class="form-container">
<p class="title">第三方登录p>
<form name="loginForm" method="post" action="http://localhost:8099/signin">
<input type="text" name="username" placeholder="用户名"/>
<br>
<input type="text" name="password" placeholder="密码"/>
<br>
<input type="text" name="_csrf" placeholder="CSRF" th:value="${csrf}"/>
<br>
<button type="submit" class="btn">登 录button>
form>
<p style="color: red" th:if="${param.error}">用户名或密码错误p>
div>
div>
body>
html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>授权title>
head>
<style>
html {
padding: 0px;
margin: 0px;
}
.title {
background-color: #E9686B;
height: 50px;
padding-left: 20%;
padding-right: 20%;
color: white;
line-height: 50px;
font-size: 18px;
}
.title-left {
float: right;
}
.title-right {
float: left;
}
.title-left a {
color: white;
}
.container {
clear: both;
text-align: center;
}
.btn {
width: 350px;
height: 35px;
line-height: 35px;
cursor: pointer;
margin-top: 20px;
border-radius: 3px;
background-color: #E9686B;
color: white;
border: none;
font-size: 15px;
}
style>
<body style="margin: 0px">
<div class="title">
<div class="title-right">OAUTH-BOOT 授权div>
<div class="title-left">
<a href="#help">帮助a>
div>
div>
<div class="container">
<h3 th:text="${clientId}+' 请求授权,该应用将获取你的以下信息'">h3>
<p>昵称,头像和性别p>
授权后表明你已同意 <a href="#boot" style="color: #E9686B">OAUTH-BOOT 服务协议a>
<form method="post" action="/oauth/authorize">
<input type="hidden" name="user_oauth_approval" value="true">
<input type="hidden" name="_csrf" th:value="${_csrf.getToken()}"/>
<button class="btn" type="submit"> 同意/授权button>
form>
div>
body>
html>
yml配置
spring:
thymeleaf:
prefix: classpath:/static/
suffix: .html
效果图如下:
收到回调后,判断states与session保存的值是否一致,防止csrf
再通过后台http调用,这里测试用的前端访问,通过code获取token
用户授权基于auth项目。
@Component
public class SsoAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String token = null;
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
if (cookie.getName().equals("SSO-TOKEN")) {
token = cookie.getValue();
}
}
if (token == null) {
response.sendRedirect("http://localhost:8099/sso/login");
return;
} else {
Map<String, Object> params = new HashMap<>();
params.put("token", token);
String result = HttpUtil.post("http://localhost:8099/sso/checkSsoToken", new HashMap<>(), params);
// 验证result
// if(Func.equals(result,"true")){
// filterChain.doFilter(request, response);
// }else{
// response.sendRedirect("http://localhost:8099/sso/login");
// return;
// }
filterChain.doFilter(request, response);
}
}
}
@Controller
@RequestMapping("/sso")
public class SsoController {
@RequestMapping("/login")
public ModelAndView login(@RequestParam Map<String, Object> map, HttpServletRequest request) throws Exception {
ModelAndView view = new ModelAndView();
view.setViewName("ssologin");
return view;
}
@RequestMapping("/success")
public String success(@RequestParam Map<String, String> map, HttpServletRequest request, HttpServletResponse response) throws Exception {
Cookie cok = new Cookie("SSO-TOKEN",map.get("token"));
cok.setHttpOnly(true);
cok.setPath("/");
response.addCookie(cok);
// 回调写死测试
return "redirect:http://localhost:8080/#/workOffice/cultureBuild/board";
}
@RequestMapping("/checkSsoToken")
public String checkSsoToken(@RequestParam Map<String, Object> map, HttpServletRequest request) throws Exception {
Object token = map.get("token");
return "true";
}
}
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>sso登录title>
head>
<style>
.login-container {
margin: 50px;
width: 100%;
}
.form-container {
margin: 0px auto;
width: 50%;
text-align: center;
box-shadow: 1px 1px 10px #888888;
height: 300px;
padding: 5px;
}
input {
margin-top: 10px;
width: 350px;
height: 30px;
border-radius: 3px;
border: 1px #E9686B solid;
padding-left: 2px;
}
.btn {
width: 350px;
height: 35px;
line-height: 35px;
cursor: pointer;
margin-top: 20px;
border-radius: 3px;
background-color: #E9686B;
color: white;
border: none;
font-size: 15px;
}
.title {
margin-top: 5px;
font-size: 18px;
color: #E9686B;
}
style>
<body>
<div class="login-container">
<div class="form-container">
<p class="title">sso登录p>
<input type="text" id="username" name="username" placeholder="用户名"/>
<br>
<input type="text" id="password" name="password" placeholder="密码"/>
<br>
<button class="btn" onclick="login()">登 录button>
div>
<script>
function login(){
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET","http://localhost:8099/oauth/token?username="+username+"&password="+password+"&grant_type=captcha&scope=all&type=account&client_id=saber&client_secret=saber_secret",false);
xmlhttp.send();
var k = xmlhttp.responseText;
// 写死token测试
window.location.href="http://localhost:8099/sso/success?token=testToken";
}
script>
div>
body>
html>
if(response.request.responseURL == "http://localhost:8099/sso/login"){
window.location.href = "http://localhost:8099/sso/login";
}