当前位置:网站首页>Microservice architecture practice: business management background and SSO design: SSO design
Microservice architecture practice: business management background and SSO design: SSO design
2022-06-26 16:59:00 【Seconds to write code】
SSO Design
Spring Security Is a powerful 、 Customizable authentication and access control framework .Spring Security OAuth2 It's based on Spring The framework supports third-party application authorization tool components . By using Spring Security OAuth2, We can perform single sign on in the merchant background (SSO) Design , So as to provide system integration for multiple microservice applications , Use unified security control management .
SSO The design is divided into two parts: server and client .SSO The server provides unified access control and authorization authentication services for each application , It's a Web UI Microservice application , In the module merchant-sso Development in , Contains the user login design 、 Home page design and authentication service design .SSO A client is a program that provides local services to users
SSO Basic configuration
SSO Basic configuration and general Web UI The application project configuration is basically the same , That is to say Web UI Based on the application project configuration , increase Spring Cloud OAuth2 The dependent quotation of , The code is as follows :
<dependency>
<group Id>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>This component already contains Security and OAuth2 Two component systems , among ,Security Provides access control functions ,OAuth2 It provides third-party application authorization and authentication services .
In the application's configuration file application.yml in , Set up SSO Service port of the application , And set a cookie Save the user's login information , The code is as follows :
server:
port:8000
session:
cookie:
name: SESSIONIDTo ensure that third-party applications can be accessed normally after authorization , We must add access to the configuration file SSO The client returns a list of addresses , And use the correct format “http:/l Domain name or IP: port /login” To set , The code is as follows ;
#SSo The client returns a list of addresses ssoclient:
redirecturis:
- http://localhost:8081/login- http://127.0.0.1:8081/1oginsso Third party application authorization design
To give access to SSO Third party applications for ( This refers to access SSO Other microservice applications for services ) To authorize , We created a configuration class AuthServerConfig, It inherited
AuthorizationServerConfigurerAdapter, The code is as follows :
@Configuration
@EnableAuthorizationServer
@EnableConfigurationProperties(clienturls.class)
public class authServerConfig extends AuthorizationServerConfigurerAdapter
CAutowired
private Clienturls clienturls;
@Override
public void configure (AuthorizationServerSecurityConfigurer oauthServer)throws Exception {
oauthServer.tokenKeyAccess( "permitAll ()")
.checkTokenAccess("isAuthenticated()");
@override
public void configure (ClientDetailsServiceConfigurer clients) throwsException {
clients.inMemory()
.withClient ( "ssoclient")
.secret(passwordEncoder ().encode ("ssosecret")).authorizedGrantTypes ("authorization_code").scopes ( "user_info")
.autoApprove(true)
.redirectUris(clienturls.getRedirecturis());
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();converter. setSigningKey ( "demoSige");
return converter;
}
aoverride
public void configure(AuthorizationServerEndpointsConfigurer endpoints)throws Exception {
endpoints.accessTokenConverter(jwtAccessTokenConverter());
}
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}In the configuration class above , It includes the following main functions :
(1) Using annotations @EnableAuthorizationServer Turn on SSO The function of the server .(2) Rewrite the first configure, Turn on use Token The function of authorizing .
(3) Rewrite the second configure, Specify the form page authorization method for the client , namely authorization_code, And set the user name and password used for client authorization as ssoclient and ssosecret. meanwhile , Import the client return address list in the configuration , And set the client return address list as redirectUris. in addition , adopt autoApprove(true) Set to automatically confirm authorization , The steps that must be confirmed manually during client authorization are omitted .
(4) Rewrite the third configure, Use safe JwtAccessToken. Here is the use of the key , We simply use one text demoSige, If you want to use a safer way , You can use KeyStore Generate keys for configuration .
sso Login authentication design
The following provides a login interface , It is used to receive the user name, password and other information entered by the user , Implement user login operation . In login authentication , Use Spring Security Verify user name and password .
Create a MyUserDetails class , Realization Spring Security Of UserDetails, The code is as follows :
public class MyUserDetails implements UserDetails {
private string username;
private String password;
private Collection<? extends GrantedAuthority> authorities;
private User user;
public MyUserDetails(String username, String password, collection<? extendsGrantedAuthority>authorities, User user){
this.username = username;
this.password = password;
this.authorities = authorities;this.user = user;
}
...
}In this way, we can import our customized user system , Provide to Spring Security Certified .
Create a MyUserDetailsService class , Realization Spring Security Of UserDetailsService, Provide user information and import user roles for the following authentication services , The code is as follows :
@component
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserService userService;
@override
public UserDetails loadUserByUsername (String username) throwsUsernameNotFoundException {
User user = userService.findByName (username);
if(user==nul1){
throw new UsernameNotFoundException(" The user doesn't exist !");
}
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
List<Role> roles =user.getRoles ();
if(roles !=null)
{
for(Role role : roles) {
SimpleGrantedAuthority authority = new
SimpleGrantedAuthority(role.getName ());
authorities.add(authority);
}
}
MyUserDetails myUserDetails = new MyUserDetails (username,
user.getPassword(),authorities, user);
return myUserDetails;
}
}such , When Spring Security When authenticating , We will call our users and get the relevant roles , This completes the user name and password verification at login , And configure corresponding permissions for users .
In order to make the above design effective , We also need to create a configuration class , namely SecurityConfng tip o Dagger inheritance 」SprngSecurity Of
WebSecurityConfigurerAdapter, The code is as follows :
@Configuration
public class SecurityConfig extends webSecurityConfigurerAdapter
@Autowired
private MyUserDetailsService myUserDetailsService;
@Autowired
@Qualifier("dataSource")
private DataSource dataSource;
@Bean(name = BeanIds.AUTHENTICATION MANAGER)Goverride
public AuthenticationManager authenticationManagerBean () throws Exception
return super.authenticationManagerBean();
@override
protected void configure (AuthenticationManagerBuilder auth)
throws Exception {
auth //lremember me
.eraseCredentials(false)
.userDetailsService (myUserDetailsService).passwordEncoder (new
BCryptPasswordEncoder());
@Override
protected void configure(HttpSecurity http) throws Exception
http.antMatcher("/**")
.authorizeRequests().antMatchers( "/login").permitAl1()
.antMatchers(" /images/**", "/checkcode", "/scripts/*
"/styles/**")
.permitAll().anyRequest().authenticated()
.and ().sessionManagement ().sessionCreationPolicy(SessionCreati
onPolicy.NEVER)
.and(.exceptionHandling().accessDeniedPage ("/deny")
.and().rememberMe ().tokenValiditySeconds (86400).tokenRepositor
y(tokenRepository())
.and()
.formLogin().loginPage ("/login" ).permitAll ().successHandler(lo
ginsuccessHandler())
.and() .logout()
.logoutUrl("/logout").permitAll().logoutSuccessUrl ("/signout");
}
@Bean
public JdbcTokenRepositoryImpl tokenRepository()
JdbcTokenRepositoryImpl jtr = new JdbcTokenRepositoryImpl()jtr.setDataSource(dataSource);
return jtr;
}
@Bean
public LoginSuccessHandler loginsuccessHandler(){
return new LoginSuccessHandler();
}
}In this configuration class , The following settings are made :
(1) Set the user service as defined above MyUserDetailsService.
(2) Specify the login page link as /login, In this way, the view file can be specified through the controller design .
(3) Specify the handler for successful login loginSuccessHandler.
4) Ignore the verification of static resources such as images .
(5) Specify the error prompt link to deny access /deny.
(6) Use rememberMe() Set to remember the user's login status .
(7) Specifies that the local data source is used to store the temporary data of user login status .
Design for the above configuration class , We create a controller , Set up a login link /login, And specify an interface design page for it login.html, The code is as follows :
@Controller
public class LoginController {
@RequestMapping( "/1ogin")public String login(){
return "login";
)
}On the interface design page login.html in , Mainly use a form design , Provide a login interface with user name, password and other input controls , The code is as follows :
...
<form th:action="@{/login}" id="loginForm" method="post">
<div class="loginTit png"></div>
<ul class="infList">
<li class="grayBox">
<label for="username" class="username-icon"></label><input id="username" class="username" name="username"
type="text" placeholder=" Your user name "/>
<div class="close png hide"></div></li>
<li class="grayBox">
<label class="pwd-icon" id="pwd"></label>
<input id="password" name="password" class="pwd"
type="password" placeholder=" The login password "/>
<div class="close png hide"></div></li>
<li class="" id="isCheckCode" style="display: none; ">
<label class="validateLabel" ></label>
<input id="checkCode" name=" checkCode" class="checkCo
type-"text" placeholder=" Verification Code "/>
<img onclick="reloadImg ();" style="cursor: pointer"
th:src="e{/images/imagecode)" id="validateImg" alt=" Verification Code "class="codePic"title-" Verification Code . Click here to update the verification code ."/>
<a class="getother" href="javascript:void(0);"
onclick="reloadImg ();" title=" Click here to update the verification code ."> to update </a>
</li>
</ul>
<ul class="infList reloadBtn" style="display: none; ">
<li>
<a href="javascript:void(0);" onclick="tologin();"> This page
It's invalid . Please click here to log in again .</a>
</li>
</u.l>
<divclass="loginBtnBo×">
div class="check-box"><input type="hidden" value="O"
id="remember-me" name="remember-me" onclick="if(this.checked) {this.value
1}else {this.value=0}"/>span class="toggleCheck no-check" id="repwd"></span> Remember me </div>
<input type="button" id="loginBtn" onclick="verSubmit()
value=" Sign in "class="loginBtn png"/>
</div>
</form>
...Complete the design of the login interface , The display effect is similar to a floating window , Pictured 10-4 Shown .

Description of verification code
When the user logs in for the first time , You can't see the verification code ; When the user fails to log in for the first time and needs to log in again , Will be asked to enter the verification code .
About the implementation of verification code , Here are two main explanations , That is, the output of the verification code and the verification of the verification code .
The output of the verification code is an image , The code is as follows :
@RequestMapping (value = " /images/imagecode")
public String imagecode (HttpServletRequest request, HttpServletResponseresponse)
throws Exception {
OutputStream os = response.getOutputStream();
Map<String, 0bject> map = ImageCode.getImageCode(60,20,os);
String simpleCaptcha = "simpleCaptcha";
request.getSession().setAttribute(simpleCaptcha,map.get("strEnsure") .toString().toLowerCase());
request.getSession().setAttribute ("codeTime", new Date() .getTime());
try {
ImageIO.write ((BufferedImage)map.get ("image"),"JPEG",0S);]catch(IOException e){
return "";
}
return null;
}That is, use... On the page “limages/imagecode” This link , You can return a verification code image consisting of several random numbers . When outputting the verification code , Use session Save the data of the verification code , Provide the basis for the verification code inspection in the next step .
About the verification of verification code , The implementation code is as follows :
@RequestMapping(value ="/checkcode")CResponseBody
public String checkcode (HttpServletRequest request,HttpSession session)
throws Exception {
String checkCode = request.getParameter("checkCode");
Object simple = session.getAttribute ("simpleCaptcha");// Verification code object if(simple == null){
request.setAttribute ("errorMsg"," The verification code has failed , Please re-enter !");return" The verification code has failed , Please re-enter !";
String captcha = simple.toString();Date now = new Date();
Long codeTime = Long.valueof(session.getAttribute ("codeTime")+"");if(StringUtils.isEmpty(checkCode) l captcha ==
null !(checkCode.equalsIgnoreCase(captcha))){
request.setAttribute( "errorMsg"," Verification code error !");return" Verification code error !";
}else if ((now.getTime ()-codeTime)/ 1000/60 >5)(// The valid length of the verification code is 5mi
request.setAttribute("errorMsg""," The verification code has failed , Please re-enter !");
return" The verification code has failed , Please re-enter !";
}else {
session.removeAttribute( "simpleCaptcha");return "1";
}
}Match the user input with the above session Compare the saved data , If the same , It can pass the inspection .
After completing the above design , When the user fails to log in for the first time , It will display as shown in the figure 10-5 The login interface shown in .

ssO Home page design
If it is in an access SSO Login in the third-party application of the service , After successful login ,SSO The server will return to the relevant application according to the link address of the application . If it's in SSO Login in the server , By default, it returns SSO The home page of the server . In the homepage design , We provide links to other applications .
SSO Home page design , It is generally composed of two parts . The first part is the design of a controller , The implementation code is as follows :
@controller
public class LoginController {
@ReguestMapping ("/")
public String index (ModelMap model, Principal principal) throws Exception{
MyUserDetails myUserDetails = (MyUserDetails)
SecurityContextHolder.getContext () .getAuthentication().getPrincipal();
User user = myUserDetails.getUser();
// List of categories ( Top menu )
List<Kind> kindList =new ArrayList<>();List<Long> kindIds = new ArrayList<>();for(Role role : user.getRoles ()){
for(Resource resource : role.getResources()){
// duplicate removal , Get a list of categories
Long kindId = resource.getModel().getKind().getId();if(! kindIds.contains(kindId)){
kindList.add(resource.getModel ().getKind());
kindIds.add (kindId);
}
}
}
model .addAttribute("kinds", kindList);
model . addAttribute("principal", principal);return "home";
}
}First , adopt SecurityContextHolder Get the complete information of the login user . then , According to login user , Relationships around users , You can sort out the top-level menus that users can access . Last , Use the classification list kinds Make this top-level menu available to the home page view .
The second part is a page view design , Among them, the design of dealing with the classification list part , stay SSO Home page home.html The navigation part of , The code is as follows :
<div class="new-icon" th:each="kind: $ {kinds}">
<div class="icon-pic">
<p><a
th:href="${'javascript:gotoService ("'+kind.link+' ", "
");')" class="linka" ><img src="/images/home/BigIconFirm. png" /</a></p>
</div>
<div class="icon-txt">
<dl>
<dt><p><a
th:hrefe"'javascript:gotoService (1''+$(kind.link}+'\',N' ');'" class="linka"th:text="${kind.name}"></a></p>
<span><img
srC=" /images/home/FourStar.jpg"/></span>
</dt></dl></div></div>It's used here Thymeleaf A loop statement of th:each, Display each record contained in the classification list on the page . Each record contains an image and a text link . among , Access to each link , Use gotoService Function to jump to the page .
After completing the above design , You can do a simple test .
start-up merchant-sso application , Enter the link shown below in the browser :http://localhost:8000
When I open the link , You can enter the login interface . Enter the user name and password generated in the previous unit test on the login interface , namely “admin/123456”. After successful login , You can open SSO The home page of , Pictured 10-6 Shown .

Be careful : chart 10-6 List of apps shown in , Will be determined by the permissions the user has . Suppose we assign more permissions to a user , Then the user will get more access to resources , Pictured 10-7 Shown .

In this article, we will explain the content of business management background and sso Design : SSO Design
- The next article will explain the background of business management and sso Design :SSO Client design ;
- Friends who think the article is good can forward this article and pay attention to Xiaobian ;
- Thank you for your support !
边栏推荐
- 知道这几个命令让你掌握Shell自带工具
- Stm32f103c8t6 realize breathing lamp code
- Use the array to calculate the average of N numbers, and output the numbers greater than the average
- Toupper function
- 并发编程整体脉络
- Teach you to learn dapr - 2 Must know concept
- When a programmer is disturbed 10 times a day, the consequences are amazing!
- 数字藏品与NFT到底有何区别
- Cache breakdown! Don't even know how to write code???
- Redis' 43 serial cannons, try how many you can carry
猜你喜欢
Scala 基础 (二):变量和数据类型

GUI+SQLServer考试系统

Cuckoo filter for Chang'an chain transaction

知道这几个命令让你掌握Shell自带工具

无需人工先验!港大&同济&LunarAI&旷视提出基于语义分组的自监督视觉表征学习,显著提升目标检测、实例分割和语义分割任务!...

Teach you to learn dapr - 3 Run the first with dapr Net program

Knowing these commands allows you to master shell's own tools

I regard it as a dry product with a monthly income of more than 30000 yuan for sidelines and more than 10000 yuan for novices!

Leetcode 1170. Frequency of occurrence of the minimum letter of the comparison string (yes, solved)

Programmer's essential toolkit, please collect!
随机推荐
Redis OM . Net redis object mapping framework
Find all primes less than or equal to Lim, store them in AA array, and return the number of primes
知道这几个命令让你掌握Shell自带工具
[机缘参悟-31]:鬼谷子-抵巇[xī]篇-危机是危险与机会并存
The first open source MySQL HTAP database in China will be released soon, and the three highlights will be notified in advance
进军AR领域,这一次罗永浩能成吗?
构造函数和析构函数
Interpretation of cloud native microservice technology trend
Structure the graduation project of actual combat camp
Call the random function to generate 20 different integers and put them in the index group of institute a
Discover K8E: minimalist kubernetes distribution
Knowing these commands allows you to master shell's own tools
Don't believe it, 98% of programmers are like this
When I was in the library, I thought of the yuan sharing mode
JUnit unit test
【MATLAB项目实战】基于卷积神经网络与双向长短时(CNN-LSTM)融合的锂离子电池剩余使用寿命预测
No manual prior is required! HKU & Tongji & lunarai & Kuangshi proposed self supervised visual representation learning based on semantic grouping, which significantly improved the tasks of target dete
电路中缓存的几种形式
Can Luo Yonghao succeed in entering the AR field this time?
Count the number of words in a line of string and take it as the return value of the function